ZMQ PUB/SUB发送重复数据问题:如何循环发送新数据?
问题分析
- 参数快照固化:
senderzmq函数接收的lat和lon是调用时的静态值,循环内部不会自动同步实例的self.lat/self.lon最新值。 - 静态方法逻辑错误:
gnss被定义为静态方法却直接操作self属性,违反Python语法——静态方法无法访问实例的self对象,应改为实例方法。 - 死循环无控制机制:发布者的
while循环没有退出条件,也无休眠逻辑,会持续占用CPU且无法响应外部更新信号。 - Socket重复创建风险:每次调用
senderzmq都重新初始化ZMQ上下文和Socket,多次调用会导致端口绑定冲突。
修正后的代码示例
发布者类完整实现
import zmq import time class GNSSPublisher: LAT0 = 0.0 # 手动配置的纬度偏移 LON0 = 0.0 # 手动配置的经度偏移 def __init__(self): # 全局初始化ZMQ资源,仅执行一次 self.context = zmq.Context() self.pub_sock = self.context.socket(zmq.PUB) self.pub_sock.bind("tcp://*:10000") self.is_running = False # 初始化坐标属性 self.lat = 0.0 self.lon = 0.0 # 改为实例方法,正确更新实例坐标 def gnss(self, event): self.lat = event.latitude + self.LAT0 self.lon = event.longitude + self.LON0 def start_publishing(self): self.is_running = True while self.is_running: # 直接读取实例最新坐标发送 self.pub_sock.send_string(f"Lat {self.lat}, Lon={self.lon}") # 添加休眠避免高频发送,可根据需求调整间隔(如0.1秒) time.sleep(0.1) def stop_publishing(self): # 提供优雅停止循环的方法 self.is_running = False self.pub_sock.close() self.context.term()
发布者触发逻辑
# 实例化发布者 publisher = GNSSPublisher() # 模拟GNSS事件(实际由外部硬件/服务触发) class MockGNSEvent: def __init__(self, lat, lon): self.latitude = lat self.longitude = lon # 更新坐标示例 publisher.gnss(MockGNSEvent(39.9042, 116.4074)) print(f"当前坐标:Lat {publisher.lat}, Lon={publisher.lon}") # 启动发布线程(避免阻塞主线程) import threading pub_thread = threading.Thread(target=publisher.start_publishing) pub_thread.start() # 如需停止发布,调用以下方法 # publisher.stop_publishing() # pub_thread.join()
接收者代码(修复订阅逻辑)
import zmq context = zmq.Context() sub_sock = context.socket(zmq.SUB) sub_sock.connect("tcp://192.168.1.35:10000") # 必须设置订阅规则,空字符串表示接收所有消息 sub_sock.setsockopt_string(zmq.SUBSCRIBE, "") while True: message = sub_sock.recv_string() print(message)
关键修改说明
- 修正方法类型:将
gnss改为实例方法,确保能正确更新实例的坐标属性。 - 全局初始化ZMQ资源:在类的
__init__中创建Socket,避免重复绑定端口。 - 动态读取最新值:
start_publishing直接访问self.lat/self.lon,每次发送都是最新坐标。 - 添加循环控制:用
is_running标志位实现循环启停,提供优雅退出方法。 - 优化发送频率:添加
time.sleep()降低CPU占用和网络带宽消耗。 - 修复订阅逻辑:接收者必须设置
SUBSCRIBE规则,否则无法接收任何消息。
内容的提问来源于stack exchange,提问作者Raul Parada Medina
相关产品推荐
相关产品推荐

