如何停止的WebSocket客户端无需停​​止反应堆

如何停止的WebSocket客户端无需停​​止反应堆

问题描述:

我有类似蟒蛇聊天室编写打算做以下事情的应用程序:如何停止的WebSocket客户端无需停​​止反应堆

  1. 对用户输入的WebSocket服务器地址的提示。
  2. 然后创建一个连接到服务器并发送/接收消息的websocket客户端。禁用创建websocket客户端的功能。
  3. 在收到服务器的“关闭”(不是关闭帧)后,客户端应该断开连接并重新启用应用程序以创建客户端。返回1.
  4. 如果用户退出应用程序,它将退出websocket客户端(如果有一个正在运行)。

我的方法是使用主线程来处理用户输入。当用户输入时,使用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' 

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

编辑:

我结束了

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

服务器可以关闭客户端套接字,是否要处理服务器上的所有客户端错误? – dsgdfg

+0

@dsgdfg事实是,我试图复制一个现有的应用程序,但我没有自己的客户端或服务器,所以我没有代码。从我所知道的使用wireshark,我可以看到服务器发送消息“关闭”,客户端回复代码为1001的关闭帧并退出。我想要做同样的事情,但我不知道如何关闭客户端并让线程返回,以便我可以做其他工作。 – vance46

您的main_thread创建运行wsthread的新线程。 wsthread使用Twisted API。 第一个wsthread成为反应器线程。所有后续的线程是不同的,它是不确定的,如果你使用它们的Twisted API会发生什么。

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

+0

谢谢指出!我认为这可能是问题。我明白,使用单线程可能适合Twisted更好,但我需要做一些事情 - >启动websocket客户端 - >根据结果做一些事情,重复。据我所知,我需要做reactor.run()来启动websocket客户端,但它会永远阻塞。没有使用线程有没有更好的方法可以做到以上?我也有一个GUI线程,我不知道没有多线程是不是很好。 – vance46

+0

Twisted具有各种GUI集成功能。根据哪个工具包,您可能能够找到一种方法来在单个线程中运行GUI和Twisted。另外,如果您熟悉GUI编程(无论如何不需要额外的线程),那么很多这些想法也适用于Twisted。例如,你不要在Tkinter中编写'while True:'循环...你使用'after_idle' API。同样,Twisted也有API,允许你安排更多的代码稍后运行,以避免产生阻塞反应器线程的循环(并且避免被'reactor.run'块阻塞)。 –