龙卷风 websocket 消息没有收到

Tornado websocket messages aren't receiving

受这个问题的启发,我有一个非常简单的设置:

基本上,我有一个 Websocket 处理程序可以连接到许多 websocket 客户端。然后我有另一个 websocket 处理程序 'DataHandler',它会在每次收到消息时广播一条消息。

所以我制作了一个 TestHandler 实例的全局列表,并用它向所有实例广播消息

ws_clients = []

class TestHandler(tornado.websocket.WebSocketHandler):
    def open(self):
        print('open test!')
        ws_clients.append(self)
        self.random_number = random.randint(0, 101)

    def on_message(self, message):
        print(message)

        print('received', message, self, self.random_number)
        self.write_message('Message received')

    def on_close(self):
        print('closed')


class DataHandler(tornado.websocket.WebSocketHandler):
    def open(self):
        print('data open!')

    def on_message(self, message):
        for c in ws_clients:
            c.write_message('hello!')


class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r"/test_service/", TestHandler),
            (r"/data/", DataHandler),
            (r"/", httpHandler)
        ]

        tornado.web.Application.__init__(self, handlers)


ws_app = Application()
ws_app.listen(8000)
tornado.ioloop.IOLoop.instance().start()

TestHandler 可以通过地址 ws://127.0.0.1/test_service/ 正常接收消息,DataHandler 可以通过地址 ws://127.0.0.1/data/ 正常接收消息,但是每当我循环访问 ws_clients 时,我从未在 TestHandler.

我是不是做错了什么?

这是我要做的 - 我会在 TestHandler 上创建一个新方法,它将用于 一个单一的目的 - 获取消息并将其发送给所有连接的客户端。

在进入代码之前,我想指出似乎(通常)将 ws_clients 保留在 class 中而不是全局对象中更好。并使用 set 而不是 list

class TestHandler(...):
    ws_clients = set() # use set instead of list to avoid duplicate connections

    def open(self):
        self.ws_clients.add(self)

    @classmethod
    def broadcast(cls, message):
        """Takes a message and sends to all connected clients"""
        for client in cls.ws_clients:
            # here you can calculate `var` depending on each client
            client.write_message(message)

    def on_close(self):
        # remove the client from `ws_clients`
        self.ws_client.remove(self)


# then you can call TestHandler.broadcast
# from anywhere in your code
# example:

class DataHandler(...):
    ...

    def on_message(self, message):
        # pass the message to TestHandler
        # to send out to connected clients
        TestHandler.broadcast(message)