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

QoS设为2时MQTT客户端无法向Broker发布数据问题求助

解决MQTT QoS2发布失败的问题

我帮你排查下这个QoS2发布失败的问题,看你的代码里有几个关键的点没处理好,导致QoS2的交互流程无法完成——毕竟QoS2需要客户端和Broker之间多轮报文确认,比QoS0/1复杂得多。

问题1:on_connect回调函数签名错误

paho-mqtt的on_connect回调有固定的参数签名,你额外加了个qos参数,这会导致回调触发时直接抛出参数不匹配的异常,连连接成功的提示都可能打不出来。QoS2的发布依赖完整的连接初始化流程,这个异常直接打断了后续的交互。

正确的on_connect签名应该是这样:

def on_connect(client, userdata, flags, rc):

问题2:未启动客户端网络循环

你调用client.connect()只是建立了TCP连接,但MQTT客户端需要运行网络循环来处理收发报文——比如QoS2必须的PUBREC、PUBREL、PUBCOMP这些控制包,没有循环的话,客户端根本没法和Broker完成这些握手步骤,自然发布失败。

问题3:发布后直接退出程序

QoS2的发布需要好几轮报文交互,你调用publish()后程序直接结束,此时交互还没完成,报文根本没机会发送成功。

修改后的完整代码

import paho.mqtt.client as mqtt
import time

MQTT_IP = '192.168.0.23'
MQTT_PORT = 1883
client = None
MQTT_CLIENT_CONNECTED = False

def on_connect(client, userdata, flags, rc):
    global MQTT_CLIENT_CONNECTED
    if rc == 0:
        print("MQTT CONNECTION ESTABLISHED")
        print(f"Client: {client}, Userdata: {userdata}")
        MQTT_CLIENT_CONNECTED = True
    else:
        print(f"Connection failed with code {rc}")

def on_message(client, userdata, msg):
    print(f"Message arrived from {client}")
    print(f"{msg.topic} {msg.payload.decode()}")

def MQTT_CONNECTION():
    global client
    try:
        print("IN mqtt connection")
        client = mqtt.Client()
        client.on_connect = on_connect
        client.on_message = on_message
        client.connect(MQTT_IP, MQTT_PORT)
        # 启动后台网络循环,让客户端能处理MQTT报文
        client.loop_start()
        # 等1秒确保连接就绪,避免未连接就发布
        time.sleep(1)
    except Exception as error:
        print("ERROR IN MQTT CONNECTION", error)
        MQTT_CLIENT_CONNECTED = False

def publish():
    global client
    if MQTT_CLIENT_CONNECTED:
        result = client.publish("1/MB/EM/3/21/IB", 2, qos=2, retain=True)
        # 检查发布结果,0代表成功发起请求
        status = result[0]
        if status == 0:
            print("Message published successfully with QoS 2")
        else:
            print(f"Failed to publish message, status code: {status}")
        # 给QoS2的交互留足够时间,确保完成所有握手
        time.sleep(2)
    else:
        print("Cannot publish: MQTT client not connected")

if __name__ == "__main__":
    MQTT_CONNECTION()
    publish()
    # 最后停止循环并断开连接,释放资源
    client.loop_stop()
    client.disconnect()

关键修改说明

  • 删掉了on_connect里多余的qos参数,匹配paho的标准回调签名
  • 增加client.loop_start()启动后台网络循环,让客户端能处理收发的MQTT报文
  • 连接后等待1秒,确保客户端完全就绪再发布
  • 发布后等待2秒,给QoS2的多轮交互留足时间
  • 增加了发布状态检查,方便快速判断是否发起成功
  • 最后主动停止循环并断开连接,避免资源泄漏

另外,也可以确认下你的MQTT Broker是否支持QoS2——主流的比如Mosquitto都是支持的,但如果是自定义的Broker,得确认它实现了QoS2的相关逻辑哦。

内容的提问来源于stack exchange,提问作者HARSH PANDEY

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:57:18