zeromq: как сделать REQ-multip-REP? - PullRequest
0 голосов
/ 05 апреля 2020

Используя zeromq, я в основном хочу сделать шаблон 'REQ-множественный-REP': клиент отправляет 1 сообщение на сервер, а затем сервер отправляет несколько ответов до завершения. «Несколько ответов» - это для этого клиента : это не общая публикация.

Я могу сделать это сам: иметь нормальный сокет REQ-REP, и когда сервер получает запрос, он создает новый PUB, отвечает адресом этого PUB в ответе клиенту, а затем клиент передает SUB в PUB, в который сервер уже начал помещать сообщения.

Но это кажется громоздким. Есть ли способ лучше? У zeromq уже есть что-то классное для этого варианта использования?

Ответы [ 2 ]

1 голос
/ 10 апреля 2020

Пара Дилер / Маршрутизатор должна работать для вашего варианта использования, когда Запрос заменяется Дилером, а Ответ маршрутизатором.

Важной частью является поведение сокета Маршрутизатора. Любое входящее сообщение будет состоять из нескольких частей и содержать как минимум 1 фрейм «маршрутизация», 1 пустой фрейм и столько отправленных вами фреймов контента.

Любое сообщение, отправленное дилеру, будет отображать первый фрейм и использовать его, чтобы определить, какой клиент для отправки сообщения.

1 голос
/ 06 апреля 2020

Возможно, вы сможете что-то сделать с XPUB / XSUB, поддерживающим REQ / REP.

Они могут быть установлены постоянно, т. Е. Клиенты и сервер находятся в одном соединении XPUB / XSUB. Когда клиент хочет сделать запрос, он может отправить уникальное клиентское сообщение подписки через свой сокет XSUB. Сервер читает это и запоминает это. Затем клиент отправляет REQ, который снова включает сообщение о подписке в качестве одного из полей запроса. Сервер отвечает на REP, и все дальнейшие ответы сервера отправляются через его XPUB с использованием сообщения подписки, которое он ранее получил от клиента, для маркировки ответов. Все остальные клиенты, не подписанные на это, не будут получать ответы, не предназначенные для них. Затем клиент отписывается от этих ответов (после получения последнего; серверу, возможно, придется включить флаг «последний ответ» в этот последний), отправив сообщение о неполадке через свой сокет XSUB. Для следующего запроса он использует другой уникальный идентификатор клиента, так что ответы на этот запрос можно отличить от ответов на предыдущий запрос.

Это все еще не очень элегантно, но по крайней мере это не настройка все время соединения / разрыв соединений.

Псевдокод - сервер. Вам необходимо прочитать этот раздел руководства: Конверты сообщений Pub-Sub

while (run)
    zmq_poll(XPUB socket, X REP socket)
    if (ZPUB socket ready)
        zmq_recv(client subscription message)
        if (message was a subscription)
            store subscription info (i.e. the client's unique topic for responses)
        else if (message was unsubscribe)
            forget client's unique topic for responses
    else if (X REP socket ready AND client unique topic received)
        zmq_recv(client request including client topic for responses)
        process the request
        zmq_send(REP socket, first response)
        s_sendmore(XPUB socket, client's unique topic for responses)
        s_send(XPUB socket, second response)
        s_sendmore(XPUB socket, client's unique topic for responses)
        s_send(XPUB socket, third response)
    else if (X REP socket ready AND client unique topic *not* received)
       error condition
    end if
loop

и клиент

create unique topic for response (a random, unique string) // Caution - I think there's a length limit
zmq_send(ZSUB socket, '\0x01`+ unique topic string)
zmq_setsockopt(ZSUB socket, ZMQ_SUBSCRIBE, unique topic for responses) // may not be necessary - it's a ZSUB socket, and the socket may have already picked this up from the previous zmq_send().
zmq_send(REQ socket, request including unique topic string)
zmq_recv(REQ socket, first response)
zmq_recv(ZSUB socket, second response)
zmq_recv(ZSUB socket, third response)
zmq_setsockopt(ZSUB socket, ZMQ_UNSUBSCRIBE, unique topic for responses) // this may not be necessary, and the follow line might do the same thing
zmq_send(ZSUB socket, '\0x00`+ unique topic string)
...