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++后台服务器开发


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