asyncio: мультиплексирование сообщений по одному соединению через веб-сокет - PullRequest
0 голосов
/ 18 января 2019

Я использую Python 3.6, asyncio и библиотеку websockets . Я пытаюсь создать клиент для службы на основе веб-сокета, которая работает следующим образом:

Клиент может отправлять запросы JSON с пользовательскими id, method и некоторыми params. Служба ответит полезной нагрузкой JSON с теми же id эхом и data в результате вызова метода.

Я бы хотел иметь абстракцию поверх этого устройства, которая бы работала примерно так:

wsc = get_websocket_connection()

async def call_method(method, **params):
    packet = make_json_packet(method, params)
    await wsc.send(packet)
    resp = await wsc.recv()
    return decode_json_packet(resp)

async def working_code():
    separate_request = asyncio.ensure_future(call_method("quux"))

    first_result = await call_method("foo", x=1)
    second_result = await call_method("bar", y=first_result)
    print(second_result)

    return await separate_request

Теперь я ожидаю, что separate_request будет асинхронно ждать, пока обрабатываются first_result и second_result s. Но я не гарантирую, что вызов wsc.recv() вернет соответствующий ответ; фактически у меня нет никаких гарантий, что служба возвращает ответы в порядке запросов.

Я могу использовать поле id для устранения неоднозначности ответов. Но как я могу написать call_method(), чтобы он внутренне управлял запросами и возобновлял «правильную» сопрограмму при получении соответствующего ответа?

1 Ответ

0 голосов
/ 18 января 2019

когда я делал подобные вещи, прежде чем я имел тенденцию делить вещи на две части:

  1. «отправляющий код» (может быть несколькими потоками), он устанавливает, куда должны отправляться ответы (т. Е. dict из id с для функций или Future с), затем отправляет запрос и блокирует для ответа
  2. «принимающий код» (вероятно, один поток на сокет), который отслеживает весь входящий трафик и передает ответы тому, какой код заинтересован в id. это также разумное место для обработки неожиданно закрытого сокета, который должен выдвигать исключение при необходимости

это, вероятно, несколько сотен строк кода и довольно специфично для приложения ...

...