zmq req重試機制

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 參數來配置所需的多路複用模式。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章