【问题标题】:Tornado websocket server and websocket client concurrently in one loop with AsyncIOTornado websocket 服务器和 websocket 客户端同时在一个循环中与 AsyncIO
【发布时间】:2020-05-27 13:27:39
【问题描述】:

我想在同一个循环中同时运行一个 tornado websocket 服务器和一个单独的 websocket 客户端,以便我可以从单个 websocket 客户端接收数据并将其从 tornado 服务器发送到所有连接的客户端。

我可以运行 tornado 服务器,也可以运行 websocket 客户端,但是 tornado 服务器没有响应客户端请求。我收到类似“等待来自 127.0.0.1:8000 的响应”的信息。

我想我遇到了异步问题。我假设我的 websocket 客户端阻塞了整个过程......

有人有想法吗?

谢谢!

Tornado 服务器:

import os.path
import tornado.web
import tornado.websocket
import tornado.httpserver
import asyncio
from ws_client import WebsocketClient


URL = "ws://echo.websocket.org"
tornado_connections = set()
ws_echo = None

class Application(tornado.web.Application): 
   def __init__(self):
       handlers = [
           (r"/", IndexHandler),
           (r"/ws", WsHandler)
           ]
       settings = dict(
           template_path=os.path.join(os.path.dirname(__file__), "template"), 
           static_path=os.path.join(os.path.dirname(__file__), "static"), 
       )
       tornado.web.Application.__init__(self, handlers, **settings)

class IndexHandler(tornado.web.RequestHandler): 
   def get(self):
       self.render("index_test.html")

class WsHandler(tornado.websocket.WebSocketHandler): 
   async def open(self):
       if self not in tornado_connections:
           await tornado_connections.add(self)
           await ws_echo.update_connections(connections=tornado_connections)
           print('TORNADO: client connected.')

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

   def on_close(self):
       if self in tornado_connections:
           tornado_connections.remove(self)
           print('TORNADO: client disconnected.')


async def start_tornado_server():
   app = Application()
   server = tornado.httpserver.HTTPServer(app) 
   server.listen(8000)

async def start_ws_client():
   ws_echo = WebsocketClient(url=URL, connections=tornado_connections)
   await ws_echo.connect()

async def main():
   await start_tornado_server()
   asyncio.create_task(start_ws_client())

asyncio.run(main())

Websocket 客户端:

import websocket
import asyncio


class WebsocketClient:
    def __init__(self, url, connections):
        self.url = url
        self.connections = connections

    def __on_open(self):
        print('Echo client connected')
        self.ws.send("Websocket rocks!")

    def __on_message(self, msg):
        print("on_messaeg: ", msg)

    def __on_close(self):
        print("Websocket closed")

    async def connect(self):
        self.ws = websocket.WebSocketApp(
            self.url,
            on_open=self.__on_open,
            on_message=self.__on_message,
            on_close=self.__on_close,
        )
        await self.ws.run_forever()

    async def disconnect(self):
        await self.ws.close()

    async def update_connections(self, connections):
        self.connections = connections
        await print("connections: ", len(self.connections))

JavaScript Websocket 客户端:

var ws = new WebSocket("ws://127.0.0.1:8000/ws");

ws.onopen = function () {
    ws.send("Client CONNECTED");
};

ws.onmessage = function (evt) {
    document.getElementById("p1").innerHTML = evt.data;
};

ws.onclose = function () {
    console.log("Client DISCONNECTED");
};

【问题讨论】:

    标签: python-3.x websocket server client tornado


    【解决方案1】:

    websocket-client 库(或至少您正在使用的 run_forever 方法)是同步的,不能与 asyncio 结合使用,除非在其自己的线程中运行。

    相反,您需要一个异步 websocket 客户端实现,例如 Tornado's websocket_connect(或 aiohttp's ws_connect

    【讨论】:

    • 感谢 Ben,您确实为我指明了正确的方向,非常有帮助!现在使用异步 tornado websocket 客户端,应用程序可以接收 websocket 数据并响应请求处理程序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-01
    • 2018-05-21
    • 1970-01-01
    • 2023-03-07
    相关资源
    最近更新 更多