Python Tornado 中的已连接客户端列表

Posted

技术标签:

【中文标题】Python Tornado 中的已连接客户端列表【英文标题】:Connected clients list in Python Tornado 【发布时间】:2013-12-03 15:03:42 【问题描述】:

我有一个 Tornado WebSocket 服务器在由线程启动的单独进程中运行。该线程在获取要通过 websockets 发送的消息时调用我的 TornadoServer 的发布方法。

在一个单独的进程上运行 Tornado 是我发现在没有线程阻塞的情况下启动 tornado 循环的唯一方法。

在我的线程中,我通过在线程 init 方法上调用这些方法来启动龙卷风进程:

self.p = tornado_server.TornadoServer()
self.p.daemon = True
self.p.start()

在这个线程中,我有一个无限循环,它试图从队列中获取消息,如果它得到消息,它会调用self.p.publish(client, message)

到目前为止,一切都很好。

在 Tornado 流程上,我基本上实现了一个发布/订阅系统。当用户打开网页时,该页面会为特定“客户端”发送“订阅”消息,比如说。在“on_message”回调中,我将 WebSocketHandler 实例和用户想要订阅的客户端的元组附加到全局列表。

然后,发布方法应该在列表中搜索订阅消息的目标客户端的用户,并且应该调用存储在该列表中的 WebSocket 上的 write_message。

唯一不起作用的是我的“客户”列表有不同的范围或其他东西。

这是我的 tornado_server 文件的代码:

#!/usr/bin/python2
import tornado.web, tornado.websocket, tornado.ioloop, multiprocessing

clients = []

class TornadoServer(multiprocessing.Process):

    class WebSocketHandler(tornado.websocket.WebSocketHandler):
        def on_message(self, message):
            global clients
            print 'TORNADO - Received message:', str(message)
            channel, subtopic = message.split('/')
            print 'TORNADO - Subscribing:', str(subtopic)
            clients.append((self, subtopic))

        def on_close(self):
            global clients
            for websocket, client in clients:
                if self == websocket:
                    print 'TORNADO - Removed client'
                    to_remove = (self, client)
                    clients.remove(to_remove)

    def __init__(self):
        multiprocessing.Process.__init__(self)
        self.application = tornado.web.Application([(r"/tri-anim", WebSocketHandler)])
        self.application.listen(1339)

    def run(self):
        tornado.ioloop.IOLoop.current().start()

    def publish(self, client, message):
        global clients
        for websocket, websocketclient in clients:
            if websocketclient == client:
                websocket.write_message(str(message))

无论我做什么,客户总是有不同的范围。调用发布时,“客户端”始终为空。有什么办法可以让它工作吗?

【问题讨论】:

【参考方案1】:

您在父进程中调用发布,但客户端列表仅在子进程中更新。使用多处理时,每个进程都会获得所有变量的自己的副本。如果您使用线程而不是变量将被共享,但即使那样,您也需要使用 IOLoop.instance().add_callback 在调用发布的线程和 write_message 函数(必须在IOLoop 线程)。

【讨论】:

以上是关于Python Tornado 中的已连接客户端列表的主要内容,如果未能解决你的问题,请参考以下文章

Python Tornado框架(TCP层)

使用python中的Tornado模块在handsontable中渲染自定义数据

Python框架之Tornado (源码之褪去模板外衣)

在 Tornado 中保留 websocket 连接列表 [重复]

知乎为啥使用Tornado?使用Python中的多线程特性了吗

深入tornado中的IOStream