Python中ZeroMQ Poller无法接收消息的原因排查
问题分析与修复方案
你的Poller脚本没输出,主要是两个关键逻辑错误导致的,我来给你拆解并修正:
1. ROUTER和DEALER的身份不匹配,消息无法送达
ROUTER要给DEALER发消息,必须知道DEALER的身份标识(identity)。但你的ROUTER代码里硬写了identity = b'electrode-service',而DEALER的身份默认是ZeroMQ自动生成的随机值,两者根本对不上,所以消息根本发不到DEALER那边。
另外,ROUTER发送的是多部分消息([身份, 内容]),DEALER这边用recv()只能拿到第一部分(身份),正确的做法是用recv_multipart()来完整接收。
2. SUB套接字的使用搞反了绑定/连接逻辑
SUB套接字的正确用法是**连接(connect)**到PUB套接字的绑定地址,而不是自己绑定地址。你现在让SUB绑定了ipc:///tmp/fast-service,但没有对应的PUB端往这个地址发消息,SUB自然收不到任何内容。
修正后的完整代码
先改ROUTER服务器:先获取DEALER的身份再发消息
ROUTER需要先收到DEALER的一条消息,才能拿到它的身份,之后才能精准发送:
import zmq import time def main(): context = zmq.Context() router = context.socket(zmq.ROUTER) router.bind("ipc:///tmp/interface-transducer") print("等DEALER发消息过来拿身份...") # 接收DEALER的消息,第一部分就是DEALER的身份 dealer_identity, msg = router.recv_multipart() print(f"拿到DEALER身份: {dealer_identity}") # 用这个身份循环发消息 while True: router.send_multipart([dealer_identity, b'[1,2]']) print("给DEALER发了一条消息") time.sleep(1) if __name__ == "__main__": main()
再改Poller监听脚本:修正DEALER接收方式,调整SUB连接逻辑
import zmq context = zmq.Context() # DEALER部分:先给ROUTER发一条消息,把自己的身份传过去 receiver = context.socket(zmq.DEALER) # (可选)如果你想固定DEALER身份,可以手动设置,这样ROUTER不用等消息就能发 # receiver.setsockopt(zmq.IDENTITY, b'electrode-service') receiver.connect("ipc:///tmp/interface-transducer") # 发一条初始消息,让ROUTER拿到身份 receiver.send(b'我是DEALER,快给我发消息!') # SUB部分:改成连接到PUB的绑定地址 subscriber = context.socket(zmq.SUB) subscriber.connect("ipc:///tmp/fast-service") # 这里对应PUB要bind的地址 subscriber.setsockopt(zmq.SUBSCRIBE, b"10001") # 初始化Poller poller = zmq.Poller() poller.register(receiver, zmq.POLLIN) poller.register(subscriber, zmq.POLLIN) # 循环监听消息 while True: try: socks = dict(poller.poll()) except KeyboardInterrupt: print("\n用户终止程序") break if receiver in socks: # 用recv_multipart完整接收ROUTER的多部分消息 parts = receiver.recv_multipart() print(f"DEALER收到消息: {parts}") if subscriber in socks: msg = subscriber.recv() print(f"SUBSCRIBER收到消息: {msg}")
测试SUB的PUB脚本(可选)
如果要测试SUB的功能,运行这个PUB脚本:
import zmq import time def main(): context = zmq.Context() pub = context.socket(zmq.PUB) pub.bind("ipc:///tmp/fast-service") while True: # 发送带订阅前缀10001的消息 pub.send(b"10001: 这是来自PUB的测试消息") print("给SUB发了一条消息") time.sleep(2) if __name__ == "__main__": main()
启动顺序:
- 先启动ROUTER服务器
- 启动Poller监听脚本
- (可选)启动PUB脚本
这样Poller就能正常输出DEALER和SUB收到的消息啦!
内容的提问来源于stack exchange,提问作者hao123
相关产品推荐
相关产品推荐

