簡體   English   中英

鍵盤中斷,套接字和線程

[英]Keyboard interrupt, sockets and 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()

您應該在主線程中捕獲鍵盤中斷,然后向子線程發送信號以退出並重新加入主線程。 您還應該使用更多線程安全的信號進行傳輸,例如基本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...

問題是在鍵盤異常情況下,僅主線程被殺死。 因此,您需要通知線程主線程已被殺死。

不用傳遞運行作為參數,而是用它來向線程發出信號。這里是一個示例代碼。 唯一的區別是該函數不以運行作為參數,而是使用它來跟蹤。 因此,當主線程死亡時,我們將其設置為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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM