我使用下面的类听大约20个udp端口。关于如何阻止它,这个课程有一个问题。因为我在stop方法中加入线程所以我必须等待最多一秒才能使每个类停止,因为recv的超时时间为1秒。你会如何推荐我解决这个问题?
class UpdClient(threading.Thread):
def __init__(self,port):
super(UpdClient, self).__init__()
self.port = port
self.finished = False
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind(('225.0.0.10', self.port))
self.sock.settimeout(1)
def run(self):
while not self.finished:
try:
message = self.sock.recv(4096)
print("*")
except socket.timeout:
continue
def stop(self):
self.finished = True
if self.is_alive():
self.join()
print("Exiting :" + str(self.port))
答案 0 :(得分:3)
您可以采取一项简单的方法来改善这种情况:将stop
功能拆分为两个独立的功能,如下所示:
def stop(self):
self.finished = True
print("Stopping :" + str(self.port))
def wait(self):
self.stop()
if self.is_alive():
self.join()
print("Exiting :" + str(self.port))
然后这样做:
for t in threads:
t.stop()
for t in threads:
t.wait()
使用20个线程,这可以将平均停止时间从大约10秒减少到大约1.1秒。
但是如果你想要比这更好,比如保证1秒,或者平均时间低于1秒,那么就没有好的,简单的方法。一些可能不好和/或困难的选项包括:
send
根据User的建议向您自己的套接字发送消息。如果你的代码知道如何处理"垃圾"消息,或者如果您的协议使添加新消息类型变得简单,可以很容易地与"真实"消息,这应该唤醒你的线程,以便很快关闭它们。close
从客户端线程下面的套接字。在某些平台上,这会导致recv
立即失败(当然,您希望except
处理此问题)。在其他情况下,它会立即导致它(你已经处理过)。有些平台都不会发生,它只会继续阻塞。因此,您确实需要在您关注的每个平台上进行测试。 * self.daemon = True
。然后你可以通过退出而不加入它们来硬杀死所有线程。具有所暗示的所有缺点。asyncio
,twisted
或gevent
......),而不是每个客户一个帖子。*在我的头脑中,我相信Windows保证错误,Linux保证错误或继续阻止但通常继续阻止,BSD不保证任何但通常继续阻止,除了通常的EOF之外,SysV不保证任何东西。但不要相信我的头脑;测试你关心的平台。
答案 1 :(得分:-1)
在Windows下,添加以下内容:
def stop(self):
self.sock.close()
# ...
这会产生错误:
OSError: [WinError 10004] A blocking operation was interrupted by a call to WSACancelBlockingCall
线程中的。