Linux下使用ZMQ实践“发布-订阅”模型

匿名 (未验证) 提交于 2019-12-02 21:59:42

一、背景


二、相关知识

2.1 ZMQ_PUB

ZMQ_PUB     A socket of type ZMQ_PUB is used by a publisher to distribute data. Messages sent are distributed in a fan out fashion to all connected peers. The     zmq_recv(3) function is not implemented for this socket type.      When a ZMQ_PUB socket enters the mute state due to having reached the high water mark for a subscriber, then any messages that would be sent to the     subscriber in question shall instead be dropped until the mute state ends. The zmq_send() function shall never block for this socket type.

ZMQ_PUB为发布端socket类型,用于消息分发,消息以扇出的方式分发到各个连接端上。该socket类型仅支持zmq_send进行发送,不支持zmq_recv()。注意当订阅者处理速度慢的时候,需要在PUB设置合适的高水位HWM来保证消息不会丢失。

2.2 ZMQ_SUB

ZMQ_SUB     A socket of type ZMQ_SUB is used by a subscriber to subscribe to data distributed by a publisher. Initially a ZMQ_SUB socket is not subscribed to any     messages, use the ZMQ_SUBSCRIBE option of zmq_setsockopt(3) to specify which messages to subscribe to. The zmq_send() function is not implemented for     this socket type.

2.3 使用方法

使用方法为一个PUB对应多个SUB,如图所示:


三、实现

Publisher代码如下,绑定在127.0.0.1:5443 上进行监听

void test_pub(void *ctx, int times) {         int ret = 0, ix = 0;         char id[16] = {0};         char request[1024];          void *sock = zmq_socket(ctx, ZMQ_PUB);         assert(sock);          s_set_id_ex(sock, id, sizeof(id));          ret = zmq_bind(sock, "tcp://127.0.0.1:5443");         assert(ret == 0);          LOGN("Pub %s start\n", id);         for (ix = 0; ix < times; ix++) {                 snprintf(request, sizeof(request), "Data-%03s-%03d", id, ix);                 s_send(sock, request);                 LOGN("Pub %s send: %s\n", id, request);                 usleep(300 * 1000);         }         LOGN("Pub %s stop\n", id);          zmq_close(sock); }

Subscriber则进行地址连接,进行接收:

int test_sub(void *ctx) {         int ret = 0, cnt = 0;         char id[16] = {0};         char request[1024];          void *sock = zmq_socket(ctx, ZMQ_SUB);         assert(sock);          s_set_id_ex(sock, id, sizeof(id));         ret = zmq_connect(sock, "tcp://127.0.0.1:5443");         assert(ret == 0);          ret = zmq_setsockopt(sock, ZMQ_SUBSCRIBE, "", 0);         assert(ret == 0);          LOGN("Sub %s start\n", id);         while (++cnt) {                 s_recv(sock, request);                 LOGN("Sub %s recv: %s\n", id, request);                 usleep(300 * 1000);         }         LOGN("Sub %s stop\n", id);          zmq_close(sock); }

主函数入口:

int main(int argc, char *argv[]) {         void *ctx = zmq_ctx_new();         assert(ctx);          srandom(time(NULL));          if (argc > 1) {                 test_pub(ctx, atoi(argv[1]));         }         else {                 test_sub(ctx);         }         zmq_ctx_destroy(ctx);         exit(EXIT_SUCCESS); }

开启2个Subscriber、1个Publisher,执行结果:

Subscriber#1、Subscriber#2 先启动后阻塞住,开启Publisher后才收到消息:

./pubsub  [ 1528395731.593 ]: Sub 0034 start [ 1528395745.306 ]: Sub 0034 recv: Data-00B9-001 [ 1528395745.607 ]: Sub 0034 recv: Data-00B9-002 [ 1528395745.907 ]: Sub 0034 recv: Data-00B9-003 [ 1528395746.209 ]: Sub 0034 recv: Data-00B9-004 [ 1528395746.509 ]: Sub 0034 recv: Data-00B9-005 [ 1528395746.810 ]: Sub 0034 recv: Data-00B9-006 [ 1528395747.111 ]: Sub 0034 recv: Data-00B9-007 [ 1528395747.413 ]: Sub 0034 recv: Data-00B9-008 [ 1528395747.714 ]: Sub 0034 recv: Data-00B9-009
./pubsub  [ 1528395738.672 ]: Sub 00B7 start [ 1528395745.306 ]: Sub 00B7 recv: Data-00B9-001 [ 1528395745.607 ]: Sub 00B7 recv: Data-00B9-002 [ 1528395745.907 ]: Sub 00B7 recv: Data-00B9-003 [ 1528395746.209 ]: Sub 00B7 recv: Data-00B9-004 [ 1528395746.509 ]: Sub 00B7 recv: Data-00B9-005 [ 1528395746.810 ]: Sub 00B7 recv: Data-00B9-006 [ 1528395747.111 ]: Sub 00B7 recv: Data-00B9-007 [ 1528395747.413 ]: Sub 00B7 recv: Data-00B9-008 [ 1528395747.714 ]: Sub 00B7 recv: Data-00B9-009

Publisher:

./pubsub 10  [ 1528395745.004 ]: Pub 00B9 start [ 1528395745.004 ]: Pub 00B9 send: Data-00B9-000 [ 1528395745.306 ]: Pub 00B9 send: Data-00B9-001 [ 1528395745.606 ]: Pub 00B9 send: Data-00B9-002 [ 1528395745.907 ]: Pub 00B9 send: Data-00B9-003 [ 1528395746.208 ]: Pub 00B9 send: Data-00B9-004 [ 1528395746.509 ]: Pub 00B9 send: Data-00B9-005 [ 1528395746.809 ]: Pub 00B9 send: Data-00B9-006 [ 1528395747.111 ]: Pub 00B9 send: Data-00B9-007 [ 1528395747.412 ]: Pub 00B9 send: Data-00B9-008 [ 1528395747.714 ]: Pub 00B9 send: Data-00B9-009 [ 1528395748.014 ]: Pub 00B9 stop
netstat -anpt|grep pubsub tcp        0      0 127.0.0.1:5443          0.0.0.0:*               LISTEN      31141/pubsub         tcp        0      0 127.0.0.1:36680         127.0.0.1:5443          ESTABLISHED 31074/pubsub         tcp        0      0 127.0.0.1:36678         127.0.0.1:5443          ESTABLISHED 31071/pubsub         tcp        0      0 127.0.0.1:5443          127.0.0.1:36680         ESTABLISHED 31141/pubsub         tcp        0      0 127.0.0.1:5443          127.0.0.1:36678         ESTABLISHED 31141/pubsub
期间netstat查看连接状态,发现Publisher启动后,两个Subscriber才建立起socket连接;

四、结论



参考文章:


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!