zmq学习笔记

代码来自
https://www.zhihu.com/people/zhuang-zhuang-48-52/posts?page=1

简介

一个socket库。它提供的套接字可以在多种协议中传输消息。点对点连接需要显式地建立连接、销毁连接、选择协议(TCP/UDP)和处理错误等,而ZMQ屏蔽了这些细节。
常用三种通信模型,“Request-Reply “,”Publisher-Subscriber“,”Parallel Pipeline”

很自由,zmq只在乎消息的长度,可以自由选择合适的报文类型。
可以是进程与进程之间的通信,可以是节点与节点之间的通信,也可以是节点与进程之间的通信
一个客户端可以连接多个服务端

与socket区别:
1、zmq套接字是异步的,可以实现特定模式
2、TCP是一对一,ZeroMQ是多对多的,可以根据套接字类型实现一对多,一对一,多对一,或多对多
3、ZeroMQ传输消息,TCP传输字节
4、ZeroMQ 隐藏IO细节,ZeroMQ不在乎目的是否存在
5、ZeroMQ可以往多个节点发送数据,可以从多个节点接收数据

请求回应模型

请求端和回应端都可以是 1:N 的模型。通常把 1 认为是 server ,N 认为是 Client ,而ZMQ可以变为M:N
无缓存,断开连接数据就会丢失
消息是双向的,server必须send回复消息,client也必须receive服务端的回复,否则通道阻塞
客户端代码

#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;
}

服务端代码

#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



订阅发布模式

广播给所有的接收者,无缓存,断开数据丢失
接收者可以订阅多个发布者
单向数据传输
发布者代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <assert.h>
    #include <string.h>
    #include "zmq.h"

    int main()
    {
    void* context = zmq_ctx_new();
    assert(context != NULL);

    void* socket = zmq_socket(context, ZMQ_PUB);
    assert(socket != NULL);

    int ret = zmq_bind(socket, "tcp://*:5555");
    assert(ret == 0);

    int i = 0;
    while(1)
    {
    char szBuf[1024] = {0};
    snprintf(szBuf, sizeof(szBuf), "server i=%d", i);//snprintf将格式化的输出写入缓冲区
    ret = zmq_send(socket, szBuf, strlen(szBuf) + 1, 0);
    i++;

    //sleep(1);
    }

    zmq_close (socket);
    zmq_ctx_destroy (context);

    return 0;
    }



接收者代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <assert.h>
    #include "zmq.h"
    #include <thread>

    using namespace std;

    #define TRUE 1

    void Recv(void* arg)
    {
    while(TRUE)
    {
    void* socket = arg;
    printf("into while\n");
    char szBuf[1024] = {0};
    int ret = zmq_recv(socket, szBuf, sizeof(szBuf) - 1, 0);
    if (ret > 0)
    {
    printf("Recv:%s\n", szBuf);
    }
    }
    }


    void Recv2(void* arg)
    {
    while(TRUE)
    {
    void* socket = arg;
    printf("into while\n");
    char szBuf[1024] = {0};
    int ret = zmq_recv(socket, szBuf, sizeof(szBuf) - 1, 0);
    if (ret > 0)
    {
    printf("Recv2:%s\n", szBuf);
    }
    }
    }

    int main()
    {
    printf("Hello world!\n");

    void* context = zmq_ctx_new();
    assert(context != NULL);

    void* socket = zmq_socket(context, ZMQ_SUB);
    assert(socket != NULL);

    int ret = zmq_connect(socket, "tcp://localhost:5555");
    assert(ret == 0);

    ret = zmq_setsockopt(socket, ZMQ_SUBSCRIBE, "", 0);
    assert(ret == 0);
    thread t1(Recv,socket);
    thread t2(Recv2,socket);
    /*
    while(1)
    {
    printf("into while\n");
    char szBuf[1024] = {0};
    ret = zmq_recv(socket, szBuf, sizeof(szBuf) - 1, 0);
    if (ret > 0)
    {
    printf("%s\n", szBuf);
    }
    }
    */
    t1.join();
    t2.join();
    zmq_close(socket);
    zmq_ctx_destroy(context);

    return 0;
    }



makefile

    all:pub sub

    CXX=g++
    CXXFLAGS=-fPIC -std=c++11 -o
    LDFLAGS=-lzmq -lpthread

    pub:pub.cpp
    $(CXX) pub.cpp $(CXXFLAGS) pub $(LDFLAGS)

    sub:sub.cpp
    $(CXX) sub.cpp $(CXXFLAGS) sub $(LDFLAGS)
    clean:
    rm -f sub pub 



管道模型

最上面是产生任务的 分发者 ventilator
中间是执行者 worker 缓存数据,可去掉
下面是收集结果的接收者 sink
断开数据不丢失,重连继续发送
单向通道
分发者代码

#include <zmq.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
int main(void)
{
    void * context = zmq_ctx_new();
    void * sender = zmq_socket(context, ZMQ_PUSH);
    zmq_bind(sender, "tcp://*:6666");
	printf ("Press Enter when the workers are ready: ");
    getchar ();
	printf ("Sending tasks to workers...\n");
    while(1)
    { 
        const char * replyMsg = "World";
        zmq_send(sender, replyMsg, strlen(replyMsg), 0);
        printf("[Server] Sended Reply Message content == \"%s\"\n", replyMsg);
    }
 
    zmq_close(sender);
    zmq_ctx_destroy(context);
 
    return 0;
}

执行者代码

#include <zmq.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>

int main(void)
{
void * context = zmq_ctx_new();
void * recviver = zmq_socket(context, ZMQ_PULL);
zmq_connect(recviver, "tcp://localhost:6666");

void * sender = zmq_socket(context, ZMQ_PUSH);
zmq_connect(sender, "tcp://localhost:5555");

while(1)
{
char buffer [256];
int size = zmq_recv (recviver, buffer, 255, 0);
if(size < 0)
{
return -1;
}
printf("buffer:%s\n",buffer);
const char * replyMsg = "World";
zmq_send(sender, replyMsg, strlen(replyMsg), 0);
printf("[Server] Sended Reply Message content == \"%s\"\n", replyMsg);
}

zmq_close(recviver);
zmq_close(sender);
zmq_ctx_destroy(context);

return 0;
}

接收者代码

#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_PULL);
    zmq_bind(socket, "tcp://*:5555");
 
    while(1)
    { 
       	char buffer [256];
		int size = zmq_recv (socket, buffer, 255, 0);
		if(size < 0)
		{
			return -1;
		}
        printf("buffer:%s\n",buffer);
    }
 
    zmq_close(socket);
    zmq_ctx_destroy(context);
 
    return 0;
}
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值