2017-12-16 7 views
0

소켓을 사용하여 통신하는 인터페이스에서 작업하고 있습니다. 나는 동시에 데이터를주고 받는데 쓰레드를 사용해야한다.키보드 인터럽트, 소켓 및 스레드

아래 코드는 지속적으로 데이터를 보내는 모듈의 축소 버전입니다.

제 문제는 개발 중에 자주 시작하고 중지해야하지만 스레드가 일반 스크립트처럼 응용 프로그램을 중지하는 것이 불가능 해 보입니다. 다시 시작하려면 프로세스 관리자에서 프로세스를 종료해야합니다.

나는 뭔가를 오해하고 있다는 느낌이 들었습니다.

나는 주변을 둘러 보았으나 아무런 도움이되지 않도록 일관성없는 답변을 많이 보았습니다. KeyboardInterrupt 예외 처리 시도했는데 작동하지 않습니다.

아이디어가 있으십니까?

import socket 
import sys 
import threading 

running = True 
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

server_address = ('localhost', 50000) 
print ('connecting to %s port %s' % server_address) 
sock.connect(server_address) 

class TelemetryPacket: 
    state = "N/A" 

    def __init__(self, stringvalue): 
     self.state = stringvalue 

    def serialise(self): 
     return "%s" % (self.state) 

def send(running): 
    try: 
     while (running): 
      telemetry = TelemetryPacket(0).serialise() 
      sock.sendto(telemetry.encode('utf-8'), server_address) 
    except KeyboardInterrupt: 
     print ("threads successfully closed") 
     running = False 

def recv(running): 
    try: 
     while (running): 
      data = sock.recv(1) 
      if (data): 
       print("data received: %s" % data) 
    except KeyboardInterrupt: 
     print ("threads successfully closed") 
     running = False 

a = threading.Thread(target=send, args=(running,)) 
a.start() 

b = threading.Thread(target=recv, args=(running,)) 
b.start() 
+0

'양말 = socket.socket (socket.AF_INET, socket.SOCK_STREAM)'와 ** 내가하기 위해 스레드를 사용해야합니다 동일한 시간에 데이터를주고받습니다. ** 먼저 소켓 라이브러리에 대해 배웁니다. TCP 연결을 사용하여 실시간 응용 프로그램을 작성할 수 없습니다! – dsgdfg

+0

@dsgdfg 당신은 좋은 지적을합니다. 한 가지 유형의 "소켓"이 있다고 가정 했으므로이 라이브러리는 실제로 생각하지 않고 모든 UDP라고 가정했습니다. 이것은 프로토 타입 일 뿐이므로 이제는 문제가 없습니다. 나중에 적절한 해결책을 찾아 볼 것입니다. 고마워요! – Gordon13

답변

1

메인 스레드에서 키보드 인터럽트를 캡쳐 한 다음 종료하고 메인 스레드로 다시 조인하기 위해 하위 스레드로 신호를 보내야합니다. 또한, 그래서 기본 threading.Event() 같은 신호에 대한 안전 뭔가 더 스레드를 사용해야합니다

import threading 
import time 

exit_signal = threading.Event() # your global exit signal 

def send(): 
    while not exit_signal.is_set(): 
     pass # whatever you need 

def recv(): 
    while not exit_signal.is_set(): 
     pass # whatever you need 

# create the threads 
a = threading.Thread(target=send) 
b = threading.Thread(target=recv) 

# start the threads 
a.start() 
b.start() 

# create a main thread loop 
try: 
    while not exit_signal.is_set(): # enable children threads to exit the main thread, too 
     time.sleep(0.1) # let it breathe a little 
except KeyboardInterrupt: # on keyboard interrupt... 
    exit_signal.set() # send signal to all listening threads 

# join back the threads 
a.join() 
b.join() 

# and you're done... 
+0

이것은 아주 좋은 답변입니다. 지금은 훨씬 더 이해할 수 있다고 생각합니다. 구조는 단지 try/catch 만 있기 때문에 훨씬 더 깔끔하고, bool 대신 이벤트를 사용합니다. 방금 ​​예외 처리기에 socket.close()를 추가해야했습니다. 그러면 예상대로 작동합니다! 감사합니다. – Gordon13

1

문제는 키보드 예외에서만 주 스레드 만 살해된다는 것입니다. 그래서 메인 스레드가 죽었다는 것을 스레드에 알릴 필요가 있습니다.

실행을 인수로 전달하는 대신 스레드에 신호를 보내기 위해 사용하십시오. 예제 코드는 다음과 같습니다. 차이점은 함수가 인수로 실행되지 않지만 추적을 위해 함수를 사용한다는 것입니다. 그래서 메인 쓰레드가 죽을 때, 우리는 코드의 끝에서 false로 설정한다.

import socket 
import sys 
import threading 


running = True 
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

server_address = ('localhost', 50000) 
print ('connecting to %s port %s' % server_address) 
sock.bind(server_address) 

class TelemetryPacket: 
    state = "N/A" 

    def __init__(self, stringvalue): 
     self.state = stringvalue 

    def serialise(self): 
     return "%s" % (self.state) 

def send(): 
    try: 
     while (running): 
      telemetry = TelemetryPacket(0).serialise() 
      sock.sendto(telemetry.encode('utf-8'), server_address) 
    except KeyboardInterrupt: 
     print ("threads successfully closed") 


def recv(): 
    try: 
     while (running): 
      data = sock.recv(1) 
      if (data): 
       print("data received: %s" % data) 
    except KeyboardInterrupt: 
     print ("threads successfully closed") 

try: 
    a = threading.Thread(target=send) 
    a.start() 

    b = threading.Thread(target=recv) 
    b.start() 

    while True: 
     pass 

except KeyboardInterrupt: 
     print ("threads successfully closed") 
     running = False # Kill the threads 
+0

고수준의 인터럽트를 잡아 당기는 것이 스레딩 문제를 이해하는 데 도움이되었습니다. 나는 또한 잘 작동하려면 socket.close()를 추가해야했다. – Gordon13