zmq in depth

zmq in depth

深度解析ZeroMQ PUB/SUB模式,以Python语音描述

PUB操作流程
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import zmq

## 1. create zmq socket
context = zmq.Context()
socket = context.socket(zmq.PUB)

## 2. bind @ IP:PORT
#socket.bind("tcp://*:5556")
socket.bind("tcp://192.168.70.25:5556")

## 3. sending data @ topic ...
topic = "OTA"
while True:
    socket.send_string("%s %s" % (topic, "PUB xxx"))

注意:

  • 关于bind的IP地址和端口
    • 这里应该是本机的IP地址(SUB端与PUB端的IP必须严格一致,参见后续章节)
    • 这里的端口号应该是随意指定(需大于1024且避开已占用的端口号)
  • 关于topic
    • 很隐晦,send_string()的第一个参数指定了topic
    • topic的类型貌似很灵活,可以是一个字符串,也可以是一个数字
SUB操作流程
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import zmq

## 1. create zmq socket
context = zmq.Context()
socket = context.socket(zmq.SUB)

## 2. connect @ IP:PORT
#socket.connect("tcp://localhost:5556")
socket.connect("tcp://192.168.70.25:5556")

## 3. sub @ topic
topic = "OTA"       ## "OT" or "O" are also okay
if isinstance(topic, bytes):
    topic = topic.decode('ascii')

socket.setsockopt_string(zmq.SUBSCRIBE, topic)

## 4. receiving data ...
for idx in range(10):
    string = socket.recv_string()
    print(string)
    print("---------------------------")

注意:

  • 关于connect的IP地址和端口号
    • 这里的IP地址与端口号要与PUB端保持一致
  • 关于topic
    • topic必须按ascii格式编码
    • 与PUB端不同,这里要明确指定topic
    • topic并非是字符串全匹配
补充:关于IP和PORT

Demo示例代码如下:

# PUB
zmq_socket.bind("tcp://*:5556")
# SUB
zmq_socket.connect("tcp://localhost:5556")

此示例代码中,

  • PUB端向其所在机器的所有IP地址发送数据
  • SUB端只接收本机(localhost)上PUB端的消息
  • 综上,此示例代码只适用本地通信,即SUB端和PUB端都运行在同一台机器上,SUB端才能收到PUB端的消息

为了适用远程(即SUB端和PUB端不在同一台机器),双方必须使用统一的IP地址和PORT端口。根据0MQ的要求,PUB端必须使用本机上所存在的IP地址,而SUB端要connect到PUB端的地址上。总结来说,PUB端的IP地址就决定了双方通信的唯一IP地址。

举例来说,PUB端与SUB端不在同一台机器上,PUB端的IP为192.168.70.25,而SUB端的IP为192.168.70.20,双方要通信,SUB端必须在connect时指定PUB端的IP,参考源码如下:

# PUB @ 192.168.70.25
zmq_socket.bind("tcp://192.168.70.25:5556")
# SUB @ 192.168.70.20
zmq_socket.connect("tcp://192.168.70.25:5556")

注意,此种情况下,该SUB端:

  • 只能接收到指定IP地址上的PUB端发来的消息
  • 接收不到其他IP地址(包括SUB端本机)上的PUB端发的消息
个人的粗浅认识:

按ZeroMQ的设计思想,是没有broker的概念,但在实际编程中,也能明显感觉到其实际上也暗含着server/client的区分,比如PUB端要zmq_socket.bind(),其可以认为是server,而SUB端要zmq_socket.connect(),其可以被认为是client,不知道这样理解是否正确。

补充:关于TOPIC

关于topic,这里想着重强调的就是其匹配模式并非是全匹配,而是子串匹配。

还是举例,SUB端订阅了“OTA”这个topic的消息,如果PUB端发出如下topic的消息,SUB端都会收到:

  • PUB端在“OTA”这个topic上发出消息,SUB端会收到;
  • PUB端在“OTAa”这个topic上发出消息,SUB端会收到;
  • PUB端在“OTA_a”这个topic上发出消息,SUB端也会收到;

也就是说,只要PUB端消息的topic开头部分能匹配SUB端订阅的topic,SUB端就能收到此消息;即使PUB端topic与SUB端订阅的topic并不完全一致,SUB端也能收到。

在定义topic时,一定要注意这个情况。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值