【发布时间】:2017-09-16 10:36:24
【问题描述】:
我有一个类似于聊天室的应用程序,用 python 编写,打算做以下事情:
- 提示用户输入 websocket 服务器地址。
- 然后创建一个连接到服务器并发送/接收消息的 websocket 客户端。禁用创建 websocket 客户端的功能。
- 从服务器接收到“关闭”(不是关闭帧)后,客户端应断开连接并重新启用应用程序以创建客户端。回到 1。
- 如果用户退出应用程序,如果有一个正在运行的 websocket 客户端,它就会退出。
我的方法是使用主线程来处理用户输入。当用户按下回车键时,使用 AutoBahn 的 twisted 模块为 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() 将永远运行,但是从第二个线程开始,它应该是非阻塞的,因为我不再启动它了。我该如何改变呢?
编辑:
我最终解决了它
- 断开连接后添加
stopFactory()。 - 用
reactor.callFromThread()制作协议函数。 - 在第一个线程中启动反应器,将客户端放在其他线程中,并使用
reactor.callInThread()创建它们。
【问题讨论】:
-
服务器可以关闭客户端套接字,你想处理服务器上的所有客户端错误吗?
-
@dsgdfg 事实上,我正在尝试复制现有应用程序,但我不拥有客户端或服务器,因此我没有代码。根据我对使用wireshark的了解,我可以看到服务器发送消息“关闭”并且客户端使用代码1001回复关闭帧并退出。我也想这样做,但我不知道如何关闭客户端并让线程返回以便我可以做其他工作。
标签: python multithreading websocket twisted autobahn