Python Quart websocket,在两个客户端之间发送数据

Posted

技术标签:

【中文标题】Python Quart websocket,在两个客户端之间发送数据【英文标题】:Python Quart websocket, send data between two clients 【发布时间】:2021-04-14 11:12:00 【问题描述】:

使用 Quart 我试图通过 websocket 从一个客户端接收数据,然后让 Quart websocket 服务器通过 websocket 将其发送到不同的客户端。

两个客户端将单独共享相同的 url,其他对客户端将有自己的 url。此回声测试分别适用于两个客户端:

@copilot_ext.websocket('/ws/<unique_id>')
async def ws(unique_id):
    while True:
        data = await websocket.receive()
        await websocket.send(f"echo data") 

我已经尝试使用https://pgjones.gitlab.io/quart/tutorials/websocket_tutorial.html#broadcasting 此处的示例进行广播,尽管我可以捕获并打印不同的 websocket,但从一个客户端向另一个客户端发送数据时运气不佳:(

connected_websockets = set()

def collect_websocket(func):
    @wraps(func)
    async def wrapper(*args, **kwargs):
        global connected_websockets
        send_channel, receive_channel = trio.open_memory_channel(2)
        connected_websockets.add(send_channel)
        try:
            return await func(send_channel, *args, **kwargs)
        finally:
            connected_websockets.remove(send_channel)
    return wrapper

@copilot_ext.websocket('/ws/<unique_id>')
@collect_websocket
async def ws(que, unique_id):
    while True:
        data = await websocket.receive()
        for send_channel in connected_websockets:
            await send_channel.send(f"message data")
            print(send_channel)

仅仅存储 websocket 对象并遍历它们也不起作用

connected_websockets = set()

@copilot_ext.websocket('/ws/<unique_id>')
async def ws(unique_id):
    global connected_websockets
    while True:
        data = await websocket.receive()
        connected_websockets.add(websocket)
        for websockett in connected_websockets:
            await websockett.send(f"message data")
            print(type(websockett))

【问题讨论】:

您能否提供一些有关您的网络或客户端设置的详细信息,您是否可能遇到防火墙问题? 不,在本地主机上运行。我也可以使用第一个测试回显发送/接收 那么你使用的是 80 端口吗? 您使用的是 Linux、mac 还是 windows? 它是一个运行在 Linux 上的 Quart 服务器。回声测试从本地主机客户端到本地主机 websocket 服务器都有效,因此网络变量已被取消 【参考方案1】:

我认为这个 sn-p 可以构成您想要实现的基础。这个想法是房间是由房间 ID 键入的队列的集合。然后每个连接的客户端在房间里都有一个队列,任何其他客户端都将消息发送到该队列。然后 send_task 在后台运行以将任何消息发送到其队列中的客户端。我希望这是有道理的,

import asyncio
from collections import defaultdict

from quart import Quart, websocket

app = Quart(__name__)

websocket_rooms = defaultdict(set)

async def send_task(ws, queue):
    while True:
        message = await queue.get()
        await ws.send(message)

@app.websocket("/ws/<id>/")
async def ws(id):
    global websocket_rooms
    queue = asyncio.Queue()
    websocket_rooms[id].add(queue)
    try:
        task = asyncio.ensure_future(send_task(websocket._get_current_object(), queue))
        while True:
            message = await websocket.receive()
            for other in websocket_rooms[id]:
                if other is not queue:
                    await other.put(message)
    finally:
        task.cancel()
        await task
        websocket_rooms[id].remove(queue)

【讨论】:

以上是关于Python Quart websocket,在两个客户端之间发送数据的主要内容,如果未能解决你的问题,请参考以下文章

Quart,聊天服务器示例

Python Quart 无法正确呈现 HTML

Telethon,全局变量停止 websocket

Python Quart/Hypercorn 流式响应导致 net::ERR_HTTP2_PROTOCOL_ERROR 200

爬虫实战国家企业公示网-webapi实现

Spring整合quart初识