重头戏!ZeroMQ的发布-订阅模式详解:ZMQ_PUB、ZMQ_SUB_zmq pub sub 最多只能订1000个

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

ZMQ_PUB
  • 发布者使用类型为ZMQ_PUB的套接字来分发数据。发送的消息以扇出方式分发给所有连接的对等方
  • 在ZMQ_PUB类型的套接字上不能执行zmq_msg_recv()等接收数据的函数
  • 当ZMQ_PUB套接字由于已达到订阅者的高水位标记而进入静音状态时,将发送给有问题的订阅者的任何消息都将被丢弃,直到静音状态结束为止。关于“高水位标记”请参阅:
  • 对于该套接字类型,zmq_msg_send()函数将永远不会阻塞
ZMQ_PUB特性摘要
兼容的对等套接字
方向
发送/接收模式
入网路由策略
外发路由策略
静音状态下的操作
ZMQ_SUB
  • 订阅者使用ZMQ_SUB类型的套接字来订阅发布者分发的数据
  • ZMQ_SUB套接字创建完成之后,ZMQ_SUB套接字未订阅任何消息,请使用zmq_setsockopt()的ZMQ_SUBSCRIBE选项指定要订阅的消息
  • 在ZMQ_PUB类型的套接字上不能执行zmq_msg_recv()等接收数据的函数
ZMQ_SUB特性摘要
兼容的对等套接字
方向
发送/接收模式
入网路由策略
外发路由策略
  • 下面编写一个使用“SUB-PUB”的发布订阅演示案例:
    • **发布者:**类似于一个天气更新服务器,向订阅者发送天气更新,内容包括邮政编码、温度、湿度等信息
    • **订阅者:**它监听发布者更新的数据流,过滤只接收与特定邮政编码相关的天气信息,默认接收接收10条数据
  • 发布者代码如下:
// 源码链接:https://github.com/dongyusheng/csdn-code/blob/master/ZeroMQ/wuserver.c
// wuserver.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <zmq.h>

// 随机生成0...num-1的随机数
#define randof(num)  (int) ((float) (num) * random () / (RAND_MAX + 1.0))

// 将string消息格式化为zmq_meg_t对象, 然后发往socket套接字上
static int s_send(void *socket, char *string);

int main()
{
    // 1.初始化上下文
    void *context = zmq_ctx_new();

    // 2.创建、绑定套接字
    void *publisher = zmq_socket(context, ZMQ_PUB);
    assert(publisher != NULL);

    // 此处我们将发布者绑定到一个tcp节点上和一个ipc节点上, 但是本案例我们只使用tcp, ipc那个只是演示说明zmq的套接字可以绑定到多个节点上
    int rc = zmq_bind(publisher, "tcp://*:5555");
    assert(rc == 0);
    rc = zmq_bind(publisher, "ipc://weather.ipc");
    assert(rc == 0);

    // 3.初始化随机数发生器
    srandom((unsigned)time(NULL));

    // 4.循环发送数据
    while(1)
    {
        // 5.随机生成邮政编码、温度、适度
        int zipcode, temperature, relhumidity;
        zipcode = randof(100000);
        temperature = randof(215) - 80;
        relhumidity = randof(50) + 10;

        // 6.将消息发送给所有的订阅者
        char update[20];
        sprintf(update, "%05d %d %d", zipcode, temperature, relhumidity);
        rc = s_send(publisher, update);
        assert(rc);
    }

    // 7.关闭套接字、销毁上下文
    zmq_close(publisher);
    zmq_ctx_destroy(context);

    return 0;
}

static int s_send(void *socket, char *string)
{
    // 初始化一个zmq_msg_t对象, 分配的大小为string的大小
    zmq_msg_t msg;
    zmq_msg_init_size(&msg, strlen(string));
    memcpy(zmq_msg_data(&msg), string, strlen(string));

    // 发送数据
    int rc = zmq_msg_send(&msg, socket, 0);

    // 关闭zmq_msg_t对象
    zmq_msg_close(&msg);

    return rc;
}
  • 订阅者代码如下:
// 源码链接:https://github.com/dongyusheng/csdn-code/blob/master/ZeroMQ/wuclient.c
// wuclient.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include <zmq.h>

// 从socket接收数据, 并将数据返回
char *s_recv(void *socket);

int main(int argc, char *argv[])
{
    // 1.初始化上下文
    void *context = zmq_ctx_new();

    // 2.创建套接字、连接发布者
    void *subscriber = zmq_socket(context, ZMQ_SUB);
    assert(subscriber != NULL);
    int rc = zmq_connect(subscriber, "tcp://localhost:5555");
    assert(rc == 0);

    // 3.因为自己是订阅者, 因此需要使用设置过滤器, 显式指定自己是否需要接收什么类型的消息
    //   程序运行时可以输入参数, 参数代表邮政编码, 如果参数为空, 那么就过滤10001的消息
    char *filter = (argc > 1) ? argv[1] : "10001";
    rc = zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, filter, strlen(filter));
    assert( rc == 0);

    // 4.从发布者那里接收消息, 接收10条自己想要的数据
    int update_nbr;
    long total_temp = 0;
    for(update_nbr = 0; update_nbr < 10; update_nbr++)
    {
        // 5.接收数据
        char *string = s_recv(subscriber);
        assert(string != NULL);

        // 6.将数据中的邮政编码、温度、适度分别存储变量中
        int zipcode, temperature, relhumidity;
        sscanf(string, "%d %d %d", &zipcode, &temperature, &relhumidity);
        total_temp += temperature;
        free(string);
    }

    // 7.接收完成之后, 打印一下平均温度
    printf("Average tempature for zipcode '%s' was %dF\n", filter, (int)(total_temp / update_nbr));

    // 8.关闭套接字、销毁上下文
    zmq_close(subscriber);
    zmq_ctx_destroy(context);

    return 0;
}

char *s_recv(void *socket)
{
    // 创建zmq_msg_t对象接收数据
    zmq_msg_t msg;
    zmq_msg_init(&msg);
    int size = zmq_msg_recv(&msg, socket, 0);
    if(size == -1)
    {
        return NULL;
    }

    // 将zmq_msg_t对象中的数据保存到字符串中
    char *string = (char*)malloc(size + 1);
    memcpy(string, zmq_msg_data(&msg), size);

    zmq_msg_close(&msg);
    string[size] = 0;

    return string;
}
  • 编译如下:
gcc -o wuserver wuserver.c -lzmq
gcc -o wuclient wuclient.c -lzmq
  • **一次运行如下,**左侧为发布者,右侧为订阅者,订阅者没有传入参数,因此默认订阅的是邮政编码为“10001”的数据

  • **又运行一次如下,**订阅者传入的参数为“10002”,因此订阅的是邮政编码为“10002”的数据

四、“XPUB-XSUB”套接字类型

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

LkP-1715891124230)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 20
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值