Python Quart websocket, отправка данных между двумя клиентами

#python #websocket #quart

Вопрос:

Используя 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 хотя я могу перехватывать и печатать разные веб-сайты, мне не очень повезло с отправкой данных от одного клиента к другому 🙁

 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))
 

Комментарии:

1. Можете ли вы предоставить некоторые сведения о том, как настраивается ваша сеть или клиенты, возможно ли, что у вас проблема с брандмауэром?

2. Нет, бегаю по местному хосту. Я также могу отправлять/получать эхо-сигналы с помощью первого теста

3. Итак, вы используете порт 80?

4. Вы используете Linux, mac или Windows?

5. это квартовый сервер, работающий на Linux. Сетевые переменные были отменены тем фактом, что тест echo работает как с клиентами localhost, так и с сервером localhost websocket

Ответ №1:

Я думаю, что этот фрагмент может лечь в основу того, чего вы хотите достичь. Идея состоит в том, что номера представляют собой набор очередей, которые вводятся с помощью идентификатора номера. Затем у каждого подключенного клиента есть очередь в комнате, в которую другие клиенты отправляют сообщения. Затем задача 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)