paho.mqtt.python配置用户名密码后发布返回rc=0但消息未送达问题
问题根因
- 你误解了
publish()返回rc=0的含义:该返回值仅代表消息已成功写入客户端本地出站缓冲区,不代表消息已经发送到MQTT broker,更不代表消息投递成功。 - MQTT连接是异步建立的:
client.connect()是非阻塞方法,调用后仅发起TCP连接请求,尚未完成MQTT协议握手流程,此时发布的消息会暂存本地缓冲,如果程序提前退出,消息根本没有机会被发送到broker。 - 未启动客户端网络循环:paho.mqtt依赖
loop()系列方法处理网络IO事件(包括发送缓冲消息、处理broker回执等),你的代码没有调用任何loop相关逻辑,消息一直滞留在本地缓冲中。 - 你尝试添加
client.tls_set()无效的原因:默认1883端口是明文MQTT端口,TLS加密默认对应8883端口,给明文端口配置TLS会导致连接失败,自然无法解决问题。
解决方法
你可以根据使用场景选择以下任意一种方案修改代码:
方案1:阻塞等待消息发送完成(适合一次性发布消息的场景)
调用publish()返回对象的wait_for_publish()方法,阻塞直到消息被broker确认,同时单次调用loop处理网络事件:
import os import paho.mqtt.client as mqtt def on_connect(client, userdata, flags, rc): print("connected with rc: "+str(rc)) def on_publish(client, data, result): print("data published") client = mqtt.Client() client.username_pw_set(username="test", password="test" ) client.on_connect = on_connect client.on_publish = on_publish client.connect("some-host", 1883) topic = "/something" value = "cool" # 启动单次网络循环处理连接事件 client.loop(timeout=0.5) ret = client.publish(topic, value, qos=1) # 建议QoS设为1,可确认broker收到消息 try: # 阻塞直到消息发布确认,超时时间设为2秒 ret.wait_for_publish(timeout=2) if ret.is_published(): res = { "statusCode": 200, "body": "The payload was successfully published" } else: res = { "statusCode": 500, "body": "There was an error publishing this payload" } except RuntimeError: res = { "statusCode": 500, "body": "Publish timeout" } # 处理完后断开连接 client.disconnect() client.loop(timeout=0.5) return res
方案2:启动后台网络循环(适合持续发布消息的场景)
如果你的服务需要长期运行、持续发布消息,可以启动后台loop线程:
# 连接后启动后台网络循环 client.connect("some-host", 1883) client.loop_start() # 后续可以随时调用publish发布消息,后台线程会自动处理发送逻辑 # 服务退出时调用停止loop # client.loop_stop() # client.disconnect()
内容的提问来源于stack exchange,提问作者dev_bri
相关产品推荐
相关产品推荐

