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
相关产品推荐
相关产品推荐

