停止客户端线程

2024-04-16 12:31:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我用下面的类监听大约20个udp端口。但在我如何阻止它的问题上,这门课有一个问题。因为我在stop方法中加入了线程,所以每个类都要等待一秒钟才能停止,因为recv有一秒的超时。你建议我怎么解决这个问题?在

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))

Tags: 方法端口selfinitportdefsocket线程
2条回答

有一个简单的解决方法可以改善这一点:将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))

然后这样做:

^{pr2}$

对于20个线程,这将使平均停止时间从约10秒减少到约1.1秒。在


但是如果你想要比这更好的,比如保证1秒,或者平均时间低于1秒,没有什么好的,简单的方法来解决这个问题。一些可能不好和/或硬选择包括:

  • send按照{a1}的建议,将消息发送到您自己的套接字。如果您的代码知道如何处理“垃圾”消息,或者如果您的协议简化了添加一个新的消息类型(可以很容易地与“真正的”消息区分开来),那么这应该会唤醒您的线程,以便很快关闭它们。在
  • close客户端线程下的套接字。在某些平台上,这将导致recv立即失败(当然,您需要一个except来处理这个问题)。在其他情况下,它会导致它立即EOF(您已经处理过了)。在某些平台上,都没有发生,它只是继续阻塞。所以你真的需要在你关心的每个平台上进行测试。*
  • self.daemon = True。然后,您可以通过退出而不加入它们来硬杀死所有线程。所有的缺点都暗示着。在
  • 完全重写您的应用程序以使用单线程reactor或多线程proactor(理想情况下,通过asynciotwisted、或{})之类的方式间接地使用,而不是每个客户端使用一个线程。在
  • 将1秒的等待更改为不超过100ms的循环覆盖等待(或者退出时间可以接受多长时间)。在
  • 接受1秒的时间就可以退出了。在

*首先,我认为Windows保证错误,Linux保证错误或继续阻止,但通常会继续阻止,BSD不保证任何东西,但通常会继续阻止,SysV不保证任何东西,但通常是EOFs。但是不要相信我的想法;测试一下你关心的平台。

在Windows下,添加此项:

def stop(self):
    self.sock.close()
    # ...

这将创建错误:

^{pr2}$

在线程中。

相关问题 更多 >