键盘中断,套接字和线程

时间:2017-12-16 15:53:03

标签: python multithreading sockets

我正在使用一个使用套接字进行通信的接口。我需要使用Threads来同时接收和发送数据。

以下代码是连续发送数据的模块的缩减版本。

我的问题是在开发过程中,我需要经常启动和停止,但似乎线程使得无法像普通脚本一样停止应用程序。需要在进程管理器中终止该进程才能重新启动它。

我有一种感觉,我误解了一些东西。

我环顾四周,但我看到了大量不一致的答案,我试图实施无济于事。我已经尝试过处理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()

2 个答案:

答案 0 :(得分:2)

您应该在主线程中捕获您的键盘中断,然后向您的子线程发送信号以退出并连接回主线程。您还应该使用更安全的线程来发送信号,例如基本的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...

答案 1 :(得分: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