ZMQ從入門到掌握一

ZeroMQ從入門到掌握<一>


一、ZeroMQ簡述

ZeroMQ是一種基於消息隊列的多線程網絡庫,其對套接字類型、連接處理、幀、甚至路由的底層細節進行抽象,提供跨越多種傳輸協議的套接字。引用雲風的話來說:ZeroMQ 並不是一個對 socket 的封裝,不能用它去實現已有的網絡協議。它有自己的模式,不同於更底層的點對點通訊模式。它有比 tcp 協議更高一級的協議。(當然 ZeroMQ 不一定基於 TCP 協議,它也可以用於進程間和進程內通訊)它改變了通訊都基於一對一的連接這個假設。ZeroMQ 把通訊的需求看成四類。其中一類是一對一結對通訊,用來支持傳統的 TCP socket 模型,但並不推薦使用。常用的通訊模式只有三類:

  1. 請求迴應模型。由請求端發起請求,並等待迴應端迴應請求。從請求端來看,一定是一對對收發配對的;反之,在迴應端一定是發收對。請求端和迴應端都可以是 1:N 的模型。通常把 1 認爲是 server ,N 認爲是 Client 。ZeroMQ 可以很好的支持路由功能(實現路由功能的組件叫作 Device),把 1:N 擴展爲 N:M (只需要加入若干路由節點)。從這個模型看,更底層的端點地址是對上層隱藏的。每個請求都隱含有迴應地址,而應用則不關心它。

  2. 發佈訂閱模型。這個模型裏,發佈端是單向只發送數據的,且不關心是否把全部的信息都發送給訂閱端。如果發佈端開始發佈信息的時候,訂閱端尚未連接上來,這些信息直接丟棄。不過一旦訂閱端連接上來,中間會保證沒有信息丟失。同樣,訂閱端則只負責接收,而不能反饋。如果發佈端和訂閱端需要交互(比如要確認訂閱者是否已經連接上),則使用額外的 socket 採用請求迴應模型滿足這個需求。

  3. 管道模型。這個模型裏,管道是單向的,從 PUSH 端單向的向 PULL 端單向的推送數據流。

    ​ ------來源於說明文件


    二、案例

    請求迴應模型

    cli.cpp

    #include <zmq.h>
    #include <string.h>
    #include <stdio.h>
    #include <unistd.h>
     
    int main(void)
    {
        printf("Connecting to server...\n");
     
        void * context = zmq_ctx_new();
        void * socket = zmq_socket(context, ZMQ_REQ);
        zmq_connect(socket, "tcp://localhost:6666");
     
        while(1)
        {
            char buffer[10];
            const char * requestMsg = "Hello";
            int bytes = zmq_send(socket, requestMsg, strlen(requestMsg), 0);
            printf("[Client][%d] Sended Request Message: %d bytes, content == \"%s\"\n", i, bytes, requestMsg);
     
            bytes = zmq_recv(socket, buffer, 10, 0);
            buffer[bytes] = '\0';
            printf("[Client][%d] Received Reply Message: %d bytes, content == \"%s\"\n", i, bytes, buffer);
     
        }
     
        zmq_close(socket);
        zmq_ctx_destroy(context);
     
        return 0;
    }
    
    

    ser.cpp

    #include <zmq.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <assert.h>
     
    int main(void)
    {
        void * context = zmq_ctx_new();
        void * socket = zmq_socket(context, ZMQ_REP);
        zmq_bind(socket, "tcp://*:6666");
     
        while(1)
        {
            char buffer[10];
            int bytes = zmq_recv(socket, buffer, 10, 0);
            buffer[bytes] = '\0';
            printf("[Server] Recevied Request Message: %d bytes, content == \"%s\"\n", bytes, buffer);
     
            sleep(1);
     
            const char * replyMsg = "World";
            bytes = zmq_send(socket, replyMsg, strlen(replyMsg), 0);
            printf("[Server] Sended Reply Message: %d bytes, content == \"%s\"\n", bytes, replyMsg);
        }
     
        zmq_close(socket);
        zmq_ctx_destroy(context);
     
        return 0;
    }
    
    

    makefile

    all: cli ser
    
    cli:cli.cpp
    	g++ -std=c++11 cli.cpp -o cli -lzmq -lpthread -g
    
    ser:ser.cpp
    	g++ -std=c++11 ser.cpp -o ser -lzmq -lpthread -g
    
    clean:
    	rm -f ser cli
    
    

    三、流程步驟

    請求迴應模型

    服務端:

    • zmq_ctx_new()
    • zmq_socket()
    • zmq_bind()
    • zmq_recv()
    • zmq_send()

    客戶端:

    • zmq_ctx_new()
    • zmq_socket()
    • zmq_bind()
    • zmq_send()
    • zmq_recv()

    下一章一起看看源碼,分析ZMQ的內部實現


    想了解學習更多C++後臺服務器方面的知識,請關注:
    微信公衆號:C++後臺服務器開發


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章