python - 多个 tornado 客户端同时连接到 tornado 服务器

python - Multiple tornado clients simultaneously connecting to tornado server

我有我的 Tornado 客户端在一个循环中不断地监听我的 Tornado 服务器,正如这里提到的 - http://tornadoweb.org/en/stable/websocket.html#client-side-support。它看起来像这样:

import tornado.websocket
from tornado import gen

@gen.coroutine
def test():
    client = yield tornado.websocket.websocket_connect("ws://localhost:9999/ws")
    client.write_message("Hello")

    while True:
        msg = yield client.read_message()
        if msg is None:
            break
        print msg

    client.close()

if __name__ == "__main__":
    tornado.ioloop.IOLoop.instance().run_sync(test)

我无法让多个客户端实例连接到服务器。第二个客户端在连接到服务器之前总是等待第一个客户端进程结束。服务器设置如下,参考自Websockets with Tornado: Get access from the "outside" to send messages to clients and

class WSHandler(tornado.websocket.WebSocketHandler):

    clients = set()

    def open(self):
        print 'new connection'
        WSHandler.clients.add(self)

    def on_message(self, message):
         print 'message received %s' % message
         # process received message
         # pass it to a thread which updates a variable
         while True:
             output = updated_variable
             self.write_message(output)

    def on_close(self):
        print 'connection closed'
        WSHandler.clients.remove(self)

application = tornado.web.Application([(r'/ws', WSHandler),])

if __name__ == "__main__":
     http_server = tornado.httpserver.HTTPServer(application)
     http_server.listen(9999)
     tornado.ioloop.IOLoop.instance().start()

但这并没有奏效——出于某种原因,即使在我成功建立了第一个连接之后,第二个连接仍然无法连接,即它甚至没有被添加到客户端集。

我最初认为 while True 不会阻止服务器接收和处理更多的客户端,但如果没有它,多个客户端就可以连接。如何在不使用 while True 的情况下从我的内部线程发回不断更新的信息?

如有任何帮助,我们将不胜感激!

要在while 循环中向客户端写入消息,可以在循环内使用yield None。这将暂停 while 循环,然后 Tornado 的 IOLoop 将可以自由接受新连接。

这是一个例子:

@gen.coroutine
def on_message(self):
    while True:
        self.write_message("Hello")
        yield None

感谢@xyres 的回答!我能够通过在 on_message 方法中启动一个线程来使其工作,该线程将处理和 while True 交给 WSHandler class 之外的函数。我相信这允许方法 运行 在 Tornado 的 IOLoop 之外,解锁新的连接。

这是我的服务器现在的样子:

def on_message(self, message):
    print 'message received %s' % message
    sendThread = threading.Thread(target=send, args=(self, message))
    sendThread.start()

def send(client, msg):
    # process received msg
    # pass it to a thread which updates a variable
    while True:
        output = updated_variable
        client.write_message(output)

其中 send 是在 class 外部定义的函数,它为我执行所需的计算并在 while True.

内部写回客户端