mosquitto_connect() 返回 MOSQ_ERR_CONN_PENDING 是正常异步连接状态,需立即调用 mosquitto_loop_start() 或 mosquitto_loop() 启动网络循环,否则连接卡住、on_connect 不触发。

mosquitto_connect() 为什么一直返回 MOSQ_ERR_CONN_PENDING
这是新手最常卡住的地方:调用 mosquitto_connect() 后没立刻连上,却误以为失败了。mosquitto 默认使用异步 I/O,这个返回值是正常流程的一部分,不是错误。
真正要做的不是重试或报错,而是启动网络循环:
- 必须在
mosquitto_connect()之后立即调用mosquitto_loop_start()(推荐)或手动轮询mosquitto_loop() - 如果用了
mosquitto_loop_start(),记得后续用mosquitto_loop_stop()清理线程 - 漏掉循环 → 连接永远卡在 pending,
on_connect回调永远不会触发 - 在单线程 CLI 工具里用
mosquitto_loop()更可控;服务类程序建议用mosquitto_loop_start()避免阻塞主逻辑
回调函数里不能直接调用 mosquitto_publish()?
可以调,但有陷阱:如果 publish 在 on_connect 里执行,而此时 broker 还没完成 CONNECT ACK 的收发流程,部分 broker(比如 EMQX 5.x)会静默丢弃这条消息。
安全做法是等 on_connect 被调用且 rc == MOSQ_ERR_SUCCESS 后,再延后一小段时间(哪怕 10ms)再发:
立即学习“C++免费学习笔记(深入)”;
- 用
std::this_thread::sleep_for(std::chrono::milliseconds(10))简单垫一下 - 更健壮的做法是发个空消息或 ping 测试通路,确认 session 已激活
- 别在
on_message回调里同步调mosquitto_publish()太多次——容易触发 broker 的 QoS 限流或本地 socket 缓冲区溢出
编译时找不到 libmosquitto.so 或链接失败
不是头文件路径问题,而是运行时动态链接路径没配对。mosquitto 库安装后通常不在系统默认路径(/usr/lib 或 /usr/local/lib),尤其用包管理器(如 apt、brew)装的版本。
- Linux 下检查:
ldconfig -p | grep mosquitto,如果没输出,说明库路径没注册 - 临时解决:
export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH(Ubuntu/Debian 路径) - CMake 中正确写法:
find_package(mosquitto REQUIRED)+target_link_libraries(your_target PRIVATE mosquitto),别手写-lmosquitto - macOS 上 brew 安装后路径通常是
/opt/homebrew/lib,需加-rpath /opt/homebrew/lib到 linker flags
订阅后收不到消息,但 on_message 回调明明注册了
常见原因不是代码逻辑,而是 QoS 和 broker 状态不匹配:
- 确保
mosquitto_subscribe()的qos参数和发布端一致;QoS 0 订阅收不到 QoS 1 发布的消息(某些 broker 严格校验) - 检查 broker 是否启用了 ACL:用户没权限订阅对应 topic,broker 不报错,只是静默过滤
- 确认 client id 是唯一的——重复 client id 会导致前一个连接被踢下线,新连接还没来得及订阅就断开了
- 用
mosquitto_sub -t 'test/topic' -v -d手动验证 broker 是否真在发消息,排除 client 端解析问题
异步库的坑往往藏在“看起来什么都没做错”的地方:连接状态、QoS 匹配、权限、client id 唯一性——这四个点漏查一个,调试时间就翻倍。











