ref: http://www.oschina.net/question/565065_116643
#include <zmq.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#define SERVER_ENDPOINT "tcp://localhost:5555"
#define REQUEST_TIMEOUT 3000 // msecs, (> 1000!)
#define REQUEST_RETRIES 3 // retry before we abandon
void *zmq_socket_new (void *context)
{
int linger = 1;
void *zsocket = zmq_socket (context, ZMQ_REQ);
zmq_setsockopt(zsocket, ZMQ_LINGER, &linger, sizeof(linger));
zmq_connect (zsocket, SERVER_ENDPOINT);
return zsocket;
}
int main (void)
{
void *context = zmq_ctx_new ();
void *zsocket = zmq_socket_new(context);
char buffer [255];
char *send_s = "Hello";
int retries_left = REQUEST_RETRIES;
while (retries_left) {
// 发送消息
zmq_send (zsocket, send_s, strlen(send_s), 0);
printf ("Send %s\n", send_s);
// 重试次数
int expect_reply = 1;
while (expect_reply) {
// 停止重试
if (retries_left == 0) {
printf("Server offline, abandoning ...\n");
break;
}
// 多路复用
zmq_pollitem_t items [] = { { zsocket, 0, ZMQ_POLLIN, 0 } };
int rc = zmq_poll (items, 1, REQUEST_TIMEOUT);
if (rc == -1) break; // Interrupted
if (items [0].revents & ZMQ_POLLIN) {
// 接收反馈
int size = zmq_recv (zsocket, buffer, 10, 0);
if (size > 255) size = 255;
buffer[size] = 0;
printf ("Recv %s\n", buffer);
if (buffer) {
retries_left = REQUEST_RETRIES;
expect_reply = 0;
}
}
// 重试连接
else {
printf("Retry connecting ...\n");
zmq_close (zsocket);
zsocket = zmq_socket_new(context);
// 重发消息
zmq_send (zsocket, send_s, strlen(send_s), 0);
printf ("Send %s\n", send_s);
--retries_left;
}
}
}
zmq_close (zsocket);
zmq_ctx_destroy (context);
return 0;
}
以上的设计模式被称之为“客户端信任”的模式,通过这种设计,我们建立了一个可控的、相对稳定的 C/S 通信模型。当然,从以上代码中我们也可以看到 ZeroMQ 中多路复用的用法,也就是 int zmq_poll (zmq_pollitem_t *items, int nitems, long timeout); 方法的使用,三个参数分别是 poll 项列表、poll 项个数以及 poll 超时时间(毫秒),其中 zmq_pollitem_t 的结构如下:
typedef struct
{
void //*socket//;
int //fd//;
short //events//;
short //revents//;
} zmq_pollitem_t;
此外,ZeroMQ 支持多种多路复用模式(参考源码 poller.hpp),列举如下:
1、select(支持unix/windows)
2、poll(支持unix)
3、epoll(支持linux)
4、kqueue(支持freebsd)
5、devpoll(zmq自研的poll)
其中,Linux 下默认使用的是 epoll 方式;当然,在编译的时候也可以通过 --with-poller 参数来配置所需的多路复用模式。