如何在pyzmq的PUB/SUB模式下发送字典并设置主题?
解决ZeroMQ PUB/SUB模式下
send_pyobj()添加主题的问题 嘿,这个问题我之前踩过坑!ZeroMQ的PUB/SUB模式里,主题是作为消息的前缀来实现过滤的,但send_pyobj()本身并没有直接的参数让你指定主题,所以你之前的代码里,SUB端订阅了主题"1",但PUB发送的消息不带主题前缀,直接就被过滤掉了,自然收不到。下面给你两种靠谱的解决方案:
方案一:用send_multipart()组合主题和Python对象
这是最符合ZeroMQ PUB/SUB设计思路的方式——把主题作为消息的第一部分,Python对象作为第二部分发送,SUB端接收时拆分出主题和对象即可。
发布端(PUB)修改后代码
import zmq port = 5555 # 替换成你实际使用的端口 context = zmq.Context() socket = context.socket(zmq.PUB) socket.bind(f"tcp://*:{port}") # 定义要使用的主题 topic = "1" # 用send_multipart发送:先转成字节的主题,再序列化的Python对象 socket.send_multipart([topic.encode('utf-8'), zmq.serialize_pyobj({'hello': 'world'})])
订阅端(SUB)修改后代码
import zmq port = 5555 # 和发布端一致 context = zmq.Context() socket = context.socket(zmq.SUB) socket.connect(f"tcp://localhost:{port}") topicfilter = "1" socket.setsockopt_string(zmq.SUBSCRIBE, topicfilter) while True: # 接收多部分消息:先拿到主题字节,再拿到序列化的对象字节 topic_bytes, obj_bytes = socket.recv_multipart() # 解析主题和对象 topic = topic_bytes.decode('utf-8') received_obj = zmq.deserialize_pyobj(obj_bytes) print(f"收到主题 [{topic}] 的消息:{received_obj}")
方案二:把主题嵌入到Python对象中(适合简单场景)
如果你的业务逻辑允许,也可以直接把主题作为字典的一个键值对,发送整个包含主题的对象,SUB端订阅所有消息后自行判断主题是否匹配。
发布端(PUB)修改后代码
import zmq port = 5555 context = zmq.Context() socket = context.socket(zmq.PUB) socket.bind(f"tcp://*:{port}") # 把主题直接加入到要发送的字典里 message = {'topic': '1', 'content': {'hello': 'world'}} socket.send_pyobj(message)
订阅端(SUB)修改后代码
import zmq port = 5555 context = zmq.Context() socket = context.socket(zmq.SUB) socket.connect(f"tcp://localhost:{port}") # 订阅所有消息(传入空字符串) socket.setsockopt_string(zmq.SUBSCRIBE, "") while True: received_obj = socket.recv_pyobj() # 自行判断主题是否匹配 if received_obj.get('topic') == '1': print(f"匹配主题的消息内容:{received_obj['content']}")
为什么原来的代码收不到消息?
ZeroMQ的SUB套接字会严格过滤消息:只有消息的前缀和订阅的主题完全匹配(或者主题是消息前缀的一部分,取决于匹配规则),才会把消息传递给应用层。你之前的PUB端直接发送Python对象,没有带主题前缀,所以SUB端直接把这些消息过滤掉了,自然打印不出内容。
内容的提问来源于stack exchange,提问作者cjm2671
相关产品推荐
相关产品推荐

