【问题标题】:ZeroMQ: How to cast a pollitem_t item, used in Poller, back to a ZeroMQ socket?ZeroMQ:如何将 Poller 中使用的 pollitem_t 项转换回 ZeroMQ 套接字?
【发布时间】:2019-11-01 17:33:24
【问题描述】:

正如标题所说,当使用 zmq::pollcppzmq 时,我希望避免将 ZeroMQ 套接字的转换硬编码为 pollitem_t item(s) 以进行轮询。

但似乎不允许我将 void* pollitem_t::socket 转换回 zmq 套接字。

我注意到官方示例代码只是在轮询后对套接字进行了硬编码。

//
//  Reading from multiple sockets in C++
//  This version uses zmq_poll()
//
// Olivier Chamoux <olivier.chamoux@fr.thalesgroup.com>

#include "zhelpers.hpp"

int main (int argc, char *argv[])
{
    zmq::context_t context(1);

    //  Connect to task ventilator
    zmq::socket_t receiver(context, ZMQ_PULL);
    receiver.connect("tcp://localhost:5557");

    //  Connect to weather server
    zmq::socket_t subscriber(context, ZMQ_SUB);
    subscriber.connect("tcp://localhost:5556");
    subscriber.setsockopt(ZMQ_SUBSCRIBE, "10001 ", 6);

    //  Initialize poll set
    zmq::pollitem_t items [] = {
        { static_cast<void*>(receiver), 0, ZMQ_POLLIN, 0 },
        { static_cast<void*>(subscriber), 0, ZMQ_POLLIN, 0 }
    };
    //  Process messages from both sockets
    while (1) {
        zmq::message_t message;
        zmq::poll (&items [0], 2, -1);
        
        if (items [0].revents & ZMQ_POLLIN) {
            receiver.recv(&message);
            //  Process task
        }
        if (items [1].revents & ZMQ_POLLIN) {
            subscriber.recv(&message);
            //  Process weather update
        }
    }
    return 0;
}

因此问题:

在这种情况下是否无法避免硬编码套接字?

【问题讨论】:

  • 您是如何尝试将items[0].socket 转换回zmq::socket_t 的?
  • zmq::socket_t sock = static_cast&lt;zmq::socket_t&gt;(pollitem.socket); this 或 zmq::socket_t* sock = static_cast&lt;zmq::socket_t*&gt;(pollitem.socket);
  • 查看 zmq 源代码,我注意到只有这个演员表:zmq::socket_base_t *s = static_cast&lt;zmq::socket_base_t *&gt; (s_); 其中s_void*
  • 是的,zmq::socket_t 有一个返回句柄的operator void*,但是没有办法返回到套接字。
  • @Botje 真可惜。当从多个套接字轮询时,我真的很想使用像 std::map 这样的容器在接收到的消息和套接字之间进行一对一的映射。但是这种民意调查使它很难实现。我唯一能想到的就是创建另一个已知套接字引用的容器,并手动将其与轮询项同步。哦,好吧。

标签: c++ sockets zeromq


【解决方案1】:

从 zmq.hpp 标头拼凑起来:

zmq::poller_t poller;
poller.add({from_handle, receiver.handle()}, event_flags::pollin});
poller.add({from_handle, subscriber.handle()}, event_flags::pollin});

// This vector must be at least as large as the number of sockets being polled
vector<zmq::poller_event> events(2);
while (true) {
  size_t num_events = poller.wait_all(events, -1);
  // You may need to sleep a bit if num_events == 0

  for (int i = 0; i < num_events; i++) {
    zmq::message message;
    events[i].socket.recv(&message);
    ...
  } 
}

编辑:意识到poller_event 结构还包含socket_ref!这让事情变得更加简单!

使用稳定的 zmq 版本,您需要 #define ZMQ_BUILD_DRAFT_API 才能使用 poller_t 及其包。

【讨论】:

  • 既然你的回答解决了我眼前的问题,我转而接受你的。谢谢!
  • 好的,我明白为什么我错过了所有这些:ZMQ_BUILD_DRAFT_API 默认是禁用的。
【解决方案2】:

Q在这种情况下,避免硬编码套接字是不可能的吗?

是的。

这是为什么部分

1)
API 记录 Poller-设置要求我们填写 pollitem_t item(s) Poller-instance 期望从我们这里收到的强制数据结构。 (所以这部分是必须的,并且有 无法想象 “避免”- 技巧可能在这里 - 不透明 void* 必须交付给 Poller 以便按预期工作......确实是.poll()某事...)

2 )
“反向”转码(硬编码与否)没有必要(因此没有必要避免在这里),由于第 1 步 - 您的代码已经知道“地图” - 它已生成 1:1-map-of-pollitem_t item(s) 以强制交付给正在审查的Poller


结语:

对于Socket-instances 数量的情况,恰好是初始构建强制(即无法避免)的对象) 1:1-map-of-pollitem_t items 数据结构(你开始称之为“硬编码”部分),可以为静态案例设计一个脚本工具(用于已知Socket-instances 要处理的情况)或自适应地图生成器,它将使用您自己的托管飞行员“磁带”(您系统维护的数据结构)以及所有要处理的Socket-instances)。

【讨论】:

  • 好吧,换句话说,我很可能需要一个 3 段数据来按 ID 和接收消息从套接字列表轮询到映射 std::map&lt;MyID, zmq::message_t&gt; myMsgs:std::map&lt;MyID, zmq::socket_t&gt; mySocks;,@987654336 @,std::vector&lt;MyID&gt; myIDs,因为轮询器必须是一个数组。当pollitem_t 已经有一个套接字时,这似乎很麻烦,恕我直言。我很想投票,然后直接myPollers[i].socket.recv(...)。从用户体验的角度来看,这要求太多了吗?
  • 你看过zmq_poller API吗?这允许您将void * userdata 附加到每个单独的套接字。
  • @Botje AH,你是对的!谢谢你的提示。我完全错过了!你会这样回答吗?如果可以的话,我非常愿意投票并使其成为第二个接受的答案!
  • @Botje 您可能已经注意到,v4.3.2 的 API-doc 仍然有 wet ink,示例代码违反了刚刚发布的调用签名( cmets也保持不变)。诀窍在于使上面发布的建议“继承”为提供传递接口,用于传递指向对象的指针以进行解映射(这里通过用户数据),如上面的结语部分所述。 Q.E.D.
  • @user3666197 示例错误并不意味着 API 已损坏。你的最后一句话我也听不懂。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-03
  • 1970-01-01
相关资源
最近更新 更多