python - 如何让 Tornado websocket 客户端接收服务器通知?

标签 python python-3.x websocket tornado

我正在尝试制作一个通常向服务器发送请求并接收响应的应用程序。如果仅此而已,我会选择 HTTP 并称之为交易。但是一些对服务器的请求对其他客户端进行了更改,所以我希望服务器向所有受影响的客户端发送一条消息,要求它们更新。
为此,我选择了 WebSockets 协议(protocol)和 Tornado 库来使用 Python 来处理它。尽管存在异步,但简单的消息交换非常简单。然而,WebSocket 客户端实际上并不是那么可配置,我一直在努力让客户端监听传入的通知,而不会中断主消息交换。

服务器部分由 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()

我不知道这里发生了什么。我什至在朝着正确的方向前进吗?

最佳答案

这里有两个问题:

  1. 使用 on_message_callback 或循环 await read_message(),但不能同时使用。如果您提供回调,则消息只会传递给该回调,而不会保存以供 read_message 使用。
  2. input 是阻塞的,不能很好地与 Tornado 配合使用。在这个小玩具演示中很好,但如果你想在生产中做这样的事情,你可能想要做一些事情,比如在 sys.stdin 周围包装一个 PipeIOStream 并使用stream.read_until('\n')

关于python - 如何让 Tornado websocket 客户端接收服务器通知?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40959113/

相关文章:

python - 使用 Python 和 NLTK 绘制 N 个结果

python - pd.read_csv 无法加载 csv 文件的第一列,并且在 Excel 中打开和保存时文件大小发生变化

python - 命名字典键以便在 python 中快速查找

python - 需要 ASCII 扑克牌才能打印一行

java - 如何从普通请求调用即@RequestMapping 调用@SendTo

java - Tomcat Websocket 发送消息后关闭连接(CLOSED_ABNORMALLY)

Python 等效于 MATLAB 命令 prod

python - 将列表的一部分与Python中的完整列表进行比较

node.js - Firefox 插件中的 Socket.io

Python3 项目删除 __pycache__ 文件夹和 .pyc 文件