Я пытаюсь сделать приложение, которое обычно отправляет запрос на сервер и получает ответ. Если бы это было так, я бы пошел с HTTP и назвал это сделкой. Но некоторые запросы на сервер делают изменения для других клиентов, поэтому я хочу, чтобы сервер отправил всем затронутым клиентам сообщение, которое они должны обновить.
Для этого я выбрал протокол WebSockets и библиотеку Tornado для работы с ним с помощью Python. Простой обмен сообщениями был довольно простым, несмотря на асинхронность. Тем не менее, клиент WebSocket на самом деле не настраивается, и я изо всех сил пытался заставить клиента прослушивать входящие уведомления, не прерывая обмен сообщениями.Как сделать клиент веб-сайта Tornado получать уведомления о сервере?
Серверная часть представлена tornado.websocket.WebSocketHandler
, который имеет on_message
метод:
from tornado.websocket import WebSocketHandler
class MyHandler(WebSocketHandler):
def on_message(self, message):
print('message:', message)
И я хотел бы что-то подобное, что в клиентской части, которая представлена только функцией tornado.websocket.websocket_connect
(source) , Эта функция инициирует объект tornado.websocket.WebSocketClientConnection
(source), который имеет метод on_message
, но из-за запутанной асинхронной структуры я не смог надлежащим образом отменить его, не нарушая обмена основными сообщениями.
Еще один способ, которым я пытался пойти, был on_message_callback
. Это звучало как то, что я мог использовать, но я не мог понять, как использовать его с read_message
. Это была моя лучшая попытка:
import tornado.websocket
import tornado.ioloop
ioloop = tornado.ioloop.IOLoop.current()
def clbk(message):
print('received', message)
async def main():
url = 'server_url_here'
conn = await tornado.websocket.websocket_connect(url, io_loop = ioloop, on_message_callback=clbk)
while True:
print(await conn.read_message()) # The execution hangs here
st = input()
conn.write_message(st)
ioloop.run_sync(main)
При этом, как код сервера:
import tornado.ioloop
import tornado.web
import tornado.websocket
import os
class EchoWebSocket(tornado.websocket.WebSocketHandler):
def open(self):
self.write_message('hello')
def on_message(self, message):
self.write_message(message)
self.write_message('notification')
if __name__ == "__main__":
app = tornado.web.Application([(r"/", EchoWebSocket)])
app.listen(os.getenv('PORT', 8080))
tornado.ioloop.IOLoop.current().start()
Я не знаю, что здесь происходит. Я даже иду в правильном направлении?
А как насчет основной проблемы? Как я могу запускать регулярный обмен сообщениями и получать уведомления одновременно? – Leva7
С обратными вызовами вы можете просто избавиться от цикла while/read_message и вызвать 'conn.write_message', когда вам нужно. Трудно сделать эту работу с 'input()', но она будет работать, если времена, когда вы действительно хотите вызвать 'write_message', находятся в обратных вызовах. С помощью сопрограмм используйте «IOLoop.spawn_callback» для запуска двух сопрограмм, один из которых выполняет цикл чтения, а другой - все, что вы хотите сделать, чтобы генерировать сообщения. –