zmq与libevent共处

来源:互联网 发布:端口怎么ping 编辑:程序博客网 时间:2024/06/05 20:38

zmq与libevent共处





可能你会有这种需求,使用zmq来处理消息收发但用libevent来监听描述符。http://inercia.tumblr.com/post/3442759929/zeromq-with-libevent是zmq和libevent混用的一个完整例子。

zmq自己封装的套接字实际上也是关联到linux系统的一个描述符上,因此可以通过getsockopt提取出zmq套接字
对应的系统fd,然后注册到libevent中。不过使用上必须注意一些东西。

1.网上提醒需要先将zmq套接字上的数据全部收完,否则注册到libevent之后的事件响应会有问题,这应该跟zmq的消息分包以及边缘触发有关系。

1
2
3
4
5
6
 while(true) {
         message_t msg;
         bool more = m_sock->recv(&msg, ZMQ_NOBLOCK);
         if(!more)
             break;
 }

2.某些模式的zmq套接字与libevent共处会有问题
zmq的模式限制了套接字的收发方向和策略,因此不同模式的zmq套接字会有一些问题,
不过XREQ或者XREP这两种限制较少的模式是ok的。

3.zmq的事件触发是边缘触发,libevent的事件触发是水平触发。因此,每次响应需要把数据收完

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
OnEvent() {
        while(true) {
            uint32_t events;
            size_t sz_events = sizeof(events);
            m_sock->getsockopt(ZMQ_EVENTS, &events, &sz_events);
            if(!(events & ZMQ_POLLIN))
                break;           

            int64_t more;
            size_t more_size = sizeof(more);
            do {
                if(!m_sock->recv(&rep, ZMQ_NOBLOCK)) {                                                                                                  
                    LOG(ERROR) << "zmq_recv error : " << zmq_strerror(errno);
                    return;
                }   
                m_sock->getsockopt(ZMQ_RCVMORE, &more, &more_size);
            } while(more);
    }
}

4.即便你把上面3条都做了,使用libevent仍然可能会出现丢包的情况,以下是熊哥给出的方案。

1
2
3
4
5
6
7
8
9
while(true)
{   
    uint32_t event = 0;
    size_t eventsz = sizeof(event);
    m_sock->getsockopt(ZMQ_EVENTS, &event, &eventsz);
    if (event & ZMQ_POLLIN) 
        OnEvent();                                                             
    event_base_loop(m_event_base, EVLOOP_ONCE);
}

原创文章,转载请注明: 转载自下雨天

本文链接地址: zmq与libevent共处