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



我有一个Tornado WebSocket服务器在一个由线程启动的单独进程中运行。这个线程在获取要通过websocket发送的消息时调用我的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实例和用户想要订阅全局列表的客户端的元组。

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

唯一不起作用的是,我的"客户"列表有不同的范围或其他什么。

这是我的龙卷风服务器文件的代码:

#!/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))

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

您在父进程中调用publish,但客户端列表仅在子进程中更新。当使用多处理时,每个进程都会获得所有变量的自己的副本。如果您使用线程,变量将被共享,但即使这样,您也需要使用IOLoop.instance().add_callback在调用publish的线程和write_message函数(必须在IOLoop线程上调用)之间进行线程安全切换。

最新更新