如何在不停止reactor

时间:2017-09-16 10:36:25

标签: python multithreading websocket twisted autobahn

我有一个类似于在python中写聊天室的应用程序,它打算做以下事情:

  1. 提示用户输入websocket服务器地址。
  2. 然后创建一个连接到服务器并发送/接收消息的websocket客户端。禁用创建websocket客户端的功能。
  3. 从服务器(非关闭框架)收到“关闭”后,客户端应断开连接并重新启用应用程序以创建客户端。回到1。
  4. 如果用户退出应用程序,则退出websocket客户端(如果有一个正在运行)。
  5. 我的方法是使用主线程来处理用户输入。当用户点击进入时,使用AutoBahn的扭曲模块为WebSocketClient创建一个线程,并将一个队列传递给它。检查反应堆是否正在运行,如果不是,则启动它。 覆盖消息方法,以便在获得“关闭”时将关闭标志放入队列中。主线程将忙于检查队列,直到收到标志并返回开始。代码如下所示。

    主线程。

    def main_thread():
        while True:
            text = raw_input("Input server url or exit")
            if text == "exit":
                if myreactor:
                    myreactor.stop()
                break
            msgq = Queue.Queue()
            threading.Thread(target=wsthread, args=(text, msgq)).start()
    
            is_close = False
            while True:
                if msgq.empty() is False:
                    msg = msgq.get()
                    if msg == "close":
                        is_close = True
                    else:
                        print msg
                    if is_close:
                        break
            print 'Websocket client closed!'
    

    工厂和协议。

    class MyProtocol(WebSocketClientProtocol):
        def onMessage(self, payload, isBinary):
            msg = payload.decode('utf-8')
            self.Factory.q.put(msg)
            if msg == 'close':
                self.dropConnection(abort=True)
    
    class WebSocketClientFactoryWithQ(WebSocketClientFactory):
        def __init__(self, *args, **kwargs):
            self.queue = kwargs.pop('queue', None)
            WebSocketClientFactory.__init__(self, *args, **kwargs)
    

    客户线程。

    def wsthread(url, q):
        factory = WebSocketClientFactoryWithQ(url=url, queue=q)
        factory.protocol = MyProtocol
        connectWS(Factory)
        if myreactor is None:
            myreactor = reactor
            reactor.run()
        print 'Done'
    

    现在我遇到了问题。似乎我的客户端线程永远不会停止。即使我收到“关闭”,它似乎仍在运行,每次我尝试重新创建一个新客户端时,它都会创建一个新线程。我理解第一个线程不会停止,因为reactor.run()将永远运行,但是从第二个线程开始,它应该是非阻塞的,因为我不再启动它了。我怎么能改变它?

    修改

    我最终用

    来解决它
    1. 断开连接后添加stopFactory()
    2. 使用reactor.callFromThread()制作协议功能。
    3. 在第一个线程中启动reactor,并将客户端放在其他线程中,并使用reactor.callInThread()创建它们。

1 个答案:

答案 0 :(得分:0)

您的main_thread创建了运行wsthread的新主题。 wsthread使用Twisted API。 第一个 wsthread成为反应堆线程。所有后续线程都是不同的,如果您使用Twisted API,则未定义会发生什么。

您几乎肯定会从应用程序中删除线程的使用。要在基于Twisted的应用程序中处理控制台输入,请查看twisted.conch.stdio(不是Twisted中记录最好的部分,唉,只是你想要的)。