原始帖子: 我正在使用libevent和zmq编写C编程服务。 使用PUSH-PULL模式将Msg从python代码推送到C服务。
从zmq socket收到的fd:
void *receiver = zmq_socket (base.zmq_ctx, ZMQ_PULL);
zmq_connect (receiver, "tcp://localhost:5557");
int fd=0;
size_t fd_len = sizeof(fd);
zmq_getsockopt (receiver, ZMQ_FD, &fd, &fd_len);
使用Libevent,使用fd注册的事件用于持久性读取
struct event *read_data_on_zmq =event_new(base.evbase, fd, EV_READ | EV_PERSIST , read_data_on_zmq_cb,receiver);
event_add(read_data_on_zmq,NULL);
event_base_dispatch(base.evbase);
在回调方法上,我正在进行非阻塞接收
void read_data_on_zmq_cb(evutil_socket_t fd, short what, void *arg)
{
char *msg = calloc(1024,sizeof(char));
int size = zmq_recv (receiver, msg, 255, ZMQ_DONTWAIT);
if (size != -1)
{
puts ("is size is not -1");
printf("msg = %s\n",msg);
}
}
在python代码中,我不断向套接字发送消息。
import zmq
import time
c=zmq.Context()
s=c.socket(zmq.PUSH)
s.bind('tcp://127.0.0.1:5557')
while(True):
s.send("abc")
time.sleep(2)
问题是我只能接收一次消息,之后事件回调永远不会被击中。 如果我在zmq_recv之后在read_data_on_zmq_cb中执行zmq_connect,那么它工作正常,但我想这是多余的,而不是正确的方法。这有什么问题?
EDIT1: 除了在执行zmq_recv()之后检查ZMQ_EVENTS之外,还需要获取所有消息,因为zmq是EDGE触发的。关于EDGE三角形通知的一个很好的解释是http://funcptr.net/2012/09/10/zeromq---edge-triggered-notification/ 所以最终我的事件回调看起来像
void read_data_on_zmq_cb(evutil_socket_t fd, short what, void *arg)
{
unsigned int zmq_events;
size_t zmq_events_size = sizeof(zmq_events);
char *msg=NULL;
zmq_getsockopt (receiver, ZMQ_EVENTS, &zmq_events, &zmq_events_size);
while(zmq_events & ZMQ_POLLIN)
{
msg = calloc(1024,sizeof(char));
int size = zmq_recv (receiver, msg, 255, ZMQ_DONTWAIT);
if (size != -1) {
#ifdef DEBUG
printf("msg = %s\n",msg);
#endif
//return msg;
}
zmq_getsockopt (receiver, ZMQ_EVENTS, &zmq_events, &zmq_events_size);
}
}
答案 0 :(得分:1)
请使用代码阅读我的EDIT1以获得完整答案。 问题是: 在执行zmq_recv()后我没有重新检查ZMQ_EVENTS,因为套接字的状态发生了变化 那时候。
所以打电话
zmq_getsockopt (receiver, ZMQ_EVENTS, &fd, &fd_size);
zmq_recv()解决了我的问题。