【问题标题】:zeromq: how to do REQ-multiple-REP?zeromq:如何做 REQ-multiple-REP?
【发布时间】:2020-07-17 11:00:06
【问题描述】:

使用 zeromq,我基本上想做一个“REQ-multiple-REP”模式:客户端向服务器发送 1 条消息,然后服务器发送多个回复直到完成。 '多个回复'是给那个客户:不是一般的发布。

我可以自己滚动:有一个普通的 REQ-REP 套接字,当服务器收到请求时,它会创建一个新的 PUB,在回复客户端时使用该 PUB 的地址进行回复,然后客户端 SUB到 PUB,服务器已经开始将消息放入其中。

但这感觉很笨拙。有没有更好的办法? zeromq 是否已经为这个用例提供了一些很酷的东西?

【问题讨论】:

    标签: zeromq


    【解决方案1】:

    您也许可以使用 XPUB/XSUB 与 REQ/REP 合作执行某些操作。

    这些可以永久设置,即客户端和服务器都在同一个 XPUB/XSUB 连接上。当客户端想要发出请求时,它可以通过其 XSUB 套接字发送客户端唯一的订阅消息。服务器读取并记住它。然后,客户端发送一个 REQ,其中再次包含订阅消息作为请求的字段之一。服务器在 REP 上做出响应,并且所有进一步的服务器响应都通过其 XPUB 发送,使用它之前从客户端收到的订阅消息来标记响应。所有其他未订阅的客户将不会收到不适合自己的响应。然后,客户端通过其 XSUB 套接字发送取消订阅,从而取消订阅这些响应(在收到最后一个响应之后;服务器可能必须在最后一个响应中包含“最后一个响应”标志)。对于下一个请求,它使用不同的客户端唯一 ID,以便将该请求的响应与上一个请求的响应区分开来。

    这仍然不是非常优雅,但至少它不会一直设置/拆除套接字连接。

    伪代码 - 服务器。您需要阅读本指南的这一部分:Pub-Sub Message Envelopes

    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)
    

    【讨论】:

    • 我以前没用过 xpub/xsub,有点困惑:为什么需要两个“订阅”消息?第一个 xsub 订阅消息是必要的吗?
    • @Colin,也许不是,但我不知道 ZMQ 库的内部要求是什么。这种方式 XSUB/XPUB 正在按照文档使用,一切都会正常工作。这也是一个强大的设置;服务器知道客户端已经为回复订阅了正确的主题,也许更重要的是,客户端没有取消订阅该主题。服务器应该先读取一个 xsub,然后是一个 req,然后它会写入 rep、xpub、xpub...last xpub,然后它应该会看到 xunsub。使用 pub/sub 可能会做一些更“开放的循环”,但错误检查更少。或者,类似的东西!
    • 或任何人:我很难发现如何实际执行上述操作。除了单个图形和 3 段,没有代码,在指南中,我似乎找不到任何关于 xpub/xsub 细节的官方文档。我是否以某种方式错过了实际文档的宝库?
    • @Colin,在那里,我添加了一些伪代码。 s_send() 和 s_sendmore() 函数是 C/C++ 创建多帧消息的助手。请参阅zguide.zeromq.org/page:all#Pub-Sub-Message-Envelopes 处的 C 示例代码。
    • 啊,API来了!谢谢,我会解决这个问题的。
    【解决方案2】:

    Dealer/Router 对应该适用于您的用例,其中 Request 被 Dealer 替换,Reply 被 Router 替换。

    重要的部分是路由器套接字行为。任何传入的消息都将是多部分的,并且至少包含 1 个“路由”帧、1 个空帧以及您发送的许多内容帧。

    在经销商上发送的任何消息都会弹出第一帧并使用它来确定将消息发送到哪个客户端。

    【讨论】:

      猜你喜欢
      • 2016-11-17
      • 2014-01-03
      • 1970-01-01
      • 2013-06-07
      • 2014-10-11
      • 2017-02-13
      • 1970-01-01
      • 1970-01-01
      • 2012-06-10
      相关资源
      最近更新 更多