You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ZMQ PUB/SUB发送重复数据问题:如何循环发送新数据?

问题分析
  1. 参数快照固化:senderzmq函数接收的lat和lon是调用时的静态值,循环内部不会自动同步实例的self.lat/self.lon最新值。
  2. 静态方法逻辑错误:gnss被定义为静态方法却直接操作self属性,违反Python语法——静态方法无法访问实例的self对象,应改为实例方法。
  3. 死循环无控制机制:发布者的while循环没有退出条件,也无休眠逻辑,会持续占用CPU且无法响应外部更新信号。
  4. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 19:45:17