如何在不停止反应器的情况下停止 websocket 客户端
How to stop a websocket client without stopping reactor
我在 python 中有一个类似于聊天室的应用程序,它打算执行以下操作:
- 提示用户输入 websocket 服务器地址。
- 然后创建一个连接到服务器和 send/receive 消息的 websocket 客户端。禁用创建 websocket 客户端的能力。
- 从服务器收到 "close" 后(不是关闭帧),客户端应断开连接并重新启用应用程序以创建客户端。回到 1.
- 如果用户退出应用程序,如果有一个 运行ning,它会退出 websocket 客户端。
我的方法是使用主线程来处理用户输入。当用户按下回车键时,将使用 AutoBahn 的扭曲模块为 WebSocketClient 创建一个线程,并将一个队列传递给它。检查 reactor 是否处于 运行ning 状态,如果不是,则启动它。
覆盖消息方法以在获取 "close" 时将关闭标志放入队列中。主线程会忙于检查Queue,直到收到标志并返回开始。代码如下所示。
主线程。
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",它似乎仍然是 运行ning,并且每次我尝试重新创建一个新客户端时,它都会创建一个新线程。我知道第一个线程不会停止,因为 reactor.run()
将永远 运行,但是从第二个线程开始,它应该是非阻塞的,因为我不再启动它了。我该如何改变它?
编辑:
我最终用
解决了它
- 断开连接后添加
stopFactory()
。
- 使用
reactor.callFromThread()
创建协议函数。
- 在第一个线程中启动反应器,将客户端放在其他线程中并使用
reactor.callInThread()
创建它们。
您的 main_thread
创建了新线程 运行 wsthread
。 wsthread
使用 Twisted APIs。 first wsthread
成为反应器线程。所有后续线程都是不同的,如果你使用它们的 Twisted API 会发生什么是不确定的。
您几乎肯定应该从您的应用程序中删除线程的使用。要在基于 Twisted 的应用程序中处理控制台输入,请查看 twisted.conch.stdio
(不是 Twisted 的最佳文档部分,唉,但正是您想要的)。
我在 python 中有一个类似于聊天室的应用程序,它打算执行以下操作:
- 提示用户输入 websocket 服务器地址。
- 然后创建一个连接到服务器和 send/receive 消息的 websocket 客户端。禁用创建 websocket 客户端的能力。
- 从服务器收到 "close" 后(不是关闭帧),客户端应断开连接并重新启用应用程序以创建客户端。回到 1.
- 如果用户退出应用程序,如果有一个 运行ning,它会退出 websocket 客户端。
我的方法是使用主线程来处理用户输入。当用户按下回车键时,将使用 AutoBahn 的扭曲模块为 WebSocketClient 创建一个线程,并将一个队列传递给它。检查 reactor 是否处于 运行ning 状态,如果不是,则启动它。 覆盖消息方法以在获取 "close" 时将关闭标志放入队列中。主线程会忙于检查Queue,直到收到标志并返回开始。代码如下所示。
主线程。
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",它似乎仍然是 运行ning,并且每次我尝试重新创建一个新客户端时,它都会创建一个新线程。我知道第一个线程不会停止,因为 reactor.run()
将永远 运行,但是从第二个线程开始,它应该是非阻塞的,因为我不再启动它了。我该如何改变它?
编辑:
我最终用
解决了它- 断开连接后添加
stopFactory()
。 - 使用
reactor.callFromThread()
创建协议函数。 - 在第一个线程中启动反应器,将客户端放在其他线程中并使用
reactor.callInThread()
创建它们。
您的 main_thread
创建了新线程 运行 wsthread
。 wsthread
使用 Twisted APIs。 first wsthread
成为反应器线程。所有后续线程都是不同的,如果你使用它们的 Twisted API 会发生什么是不确定的。
您几乎肯定应该从您的应用程序中删除线程的使用。要在基于 Twisted 的应用程序中处理控制台输入,请查看 twisted.conch.stdio
(不是 Twisted 的最佳文档部分,唉,但正是您想要的)。