У меня очень простая настройка, вдохновленная этим вопросом: Tornado - Слушайте несколько клиентов одновременно над веб-сайтами
По сути, у меня есть один обработчик 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
через ws_clients
, я никогда не получаю никаких сообщений на TestHandler
.
Я делаю что-то неправильно?
Вот что я сделал бы - я бы создал новый метод TestHandler
который будет служить одной цели - взять сообщение и отправить его всем подключенным клиентам.
Прежде чем перейти к коду, я хотел бы указать, что кажется (обычно) лучше поддерживать ws_clients
внутри класса вместо глобального объекта. И используйте 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)