2017-12-16 48 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)'と**:あなたもそう、基本的なthreading.Event()のようなシグナリングのためのより多くのスレッドが安全なものを使用する必要があります同時にデータを送受信する**まず、ソケットライブラリについて学びます。 TCP接続でリアルタイムアプリケーションを書くことはできません! – dsgdfg

+0

@dsgdfgあなたは良い点を作っています。私は1つのタイプの "ソケット"があると仮定していたので、このライブラリはすべてのUDPであると仮定しました。 これは単なるプロトタイプであるため、今は問題ありません。私は間違いなく、後で適切な解決策を検討します、ありがとう! – Gordon13

答えて

1

あなたは、メインスレッドでのキーボード割り込みをキャプチャしてから終了して戻ってメインスレッドに参加するためにあなたの子供のスレッドにシグナルを送るべきです。私がするためにスレッドを使用する必要が

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が1つしかないので、私がやっていたよりもはるかにクリーンで、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

関連する問題