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

Mosquitto客户端on_connect回调持续触发问题排查求助

问题描述

本地与Mosquitto Broker同主机运行C++应用时,on_connect回调持续触发,Broker日志重复输出:

New Client connected from 10.0.2.37 as publisher-test
Client publisher-test already connected, closing old connection

以下是初始化MQTT客户端的代码:

bool MosquittoAppServer::InitMosquitto() {
    int rc = mosquitto_lib_init();
    printf("MosquittoAppServer::InitMosquitto Breeakpoint #1 - mosquitto_lib_init %s \r\n", rc==MOSQ_ERR_SUCCESS ? "succeeded" : "failed");
    mMosq = mosquitto_new("publisher-test", true, NULL);
    printf("MosquittoAppServer::InitMosquitto Breeakpoint #2A %x %s \r\n",&mMosq, mMosq == NULL ? "failed to create mosquitto obj": "successfully created mosquitto obj");
    mosquitto_connect_callback_set(mMosq, on_connect_callback);
    printf("MosquittoAppServer::InitMosquitto Breeakpoint #2B mosquitto_connect_callback_set \r\n");
    mosquitto_publish_callback_set(mMosq, on_pub_callback);
    printf("MosquittoAppServer::InitMosquitto Breeakpoint #2C mosquitto_publish_callback_set \r\n");
    mosquitto_subscribe_callback_set(mMosq, on_sub_callback);
    printf("MosquittoAppServer::InitMosquitto Breeakpoint #2D mosquitto_subscribe_callback_set \r\n");
    mosquitto_message_callback_set(mMosq, on_msg_callback);
    printf("MosquittoAppServer::InitMosquitto Breeakpoint #2E mosquitto_message_callback_set \r\n");
    mosquitto_user_data_set(mMosq,  this);
    printf("MosquittoAppServers::InitMosquitto Breeakpoint #2F mosquitto_user_data_set \r\n");
    rc = mosquitto_username_pw_set(mMosq, "mqtt_user", "P@$$#123");
    printf("MosquittoAppServer::InitMosquitto Breeakpoint #3 mosquitto_username_pw_set %s \r\n", rc==MOSQ_ERR_SUCCESS ? "succeeded" : "failed");
    
    printf("MosquittoAppServer::InitMosquitto Breeakpoint #4 about to connect to broker at address: %s \r\n", mBrokerIpAddr);
    
    rc = -1;
    rc = mosquitto_connect(mMosq, mBrokerIpAddr, 1883, 60);
    printf("MosquittoAppServer::InitMosquitto Breeakpoint #5 mosquitto_connect %s \r\n", rc==MOSQ_ERR_SUCCESS ? "succeeded" : "failed");
    if(rc != 0) {
        printf("MosquittoAppServer::InitMosquitto Client could not connect to MQTT-Broker!  Error Code: %d\n", rc);
      switch(rc) {
        case MOSQ_ERR_SUCCESS:{
            printf("MosquittoAppServer::InitMosquitto failed to connect.  Received Error MOSQ_ERR_SUCCESS \n");
            break;
        }
        case MOSQ_ERR_INVAL:{
            printf("MosquittoAppServer::InitMosquitto failed to connect.  Received Error MOSQ_ERR_INVAL \n");
            break;
        }
        case MOSQ_ERR_NOMEM:{
            printf("MosquittoAppServer::InitMosquitto failed to connect.  Received Error MOSQ_ERR_NOMEM \n");
            break;
        }
        case MOSQ_ERR_NO_CONN:{
            printf("MosquittoAppServer::InitMosquitto failed to connect.  Received Error MOSQ_ERR_NO_CONN \n");
            break;
        }
        case MOSQ_ERR_PROTOCOL:{
            printf("MosquittoAppServer::InitMosquitto failed to connect.  Received Error MOSQ_ERR_PROTOCOL \n");
            break;
        }
        case MOSQ_ERR_PAYLOAD_SIZE:{
            printf("MosquittoAppServer::InitMosquitto failed to connect.  Received Error MOSQ_ERR_PAYLOAD_SIZE \n");
            break;
        }
        case MOSQ_ERR_MALFORMED_UTF8:{
            printf("MosquittoAppServer::InitMosquitto failed to connect.  Received Error MOSQ_ERR_MALFORMED_UTF8 \n");
            break;
        }
        case MOSQ_ERR_QOS_NOT_SUPPORTED:{
            printf("MosquittoAppServer::InitMosquitto failed to connect.  Received Error MOSQ_ERR_QOS_NOT_SUPPORTED \n");
            break;
        }
        case MOSQ_ERR_OVERSIZE_PACKET:{
            printf("MosquittoAppServer::InitMosquitto failed to connect.  Received Error MOSQ_ERR_OVERSIZE_PACKET \n");
            break;
        }
      }
        mosquitto_destroy(mMosq);
        return;// -1;
    }
    printf("MosquittoAppServer::InitMosquitto Breeakpoint #6 - Now connected to the broker \r\n");  
    rc = mosquitto_publish(mMosq, NULL, "my-mqtt-topic", sizeof("Hello from a cleint!"), "Hello from a client!", 0, false);     
    rc = mosquitto_loop_start(mMosq);
    printf("MosquittoAppServer::InitMosquitto Breeakpoint #8  - mosquitto_loop_start  result: %s \r\n", rc==MOSQ_ERR_SUCCESS ? "succeeded" : "failed");
    
    printf("MosquittoAppServer::InitMosquitto Breeakpoint THE END \r\n");
    
    return rc == 0;
}
原因分析
  1. 重复调用初始化函数:InitMosquitto被多次执行,每次都会创建新的客户端实例并使用固定IDpublisher-test连接Broker,Broker因ID冲突踢掉旧连接,新连接触发on_connect回调,形成循环。
  2. 固定客户端ID未处理生命周期:代码使用固定客户端ID,且clean_session设为true,若旧客户端实例未被销毁就发起新连接,Broker会强制关闭旧连接;若旧实例后台仍在尝试通信,会触发重连,进一步加剧循环。
  3. 客户端实例未正确销毁:如果mMosq是类成员变量,多次调用InitMosquitto会覆盖旧指针,导致旧实例未被销毁,持续与Broker交互引发冲突。
解决方法
  1. 限制初始化函数仅执行一次
    添加初始化标志位,避免重复创建客户端:
bool MosquittoAppServer::InitMosquitto() {
    static bool isInitialized = false;
    if (isInitialized) {
        printf("MosquittoAppServer already initialized\n");
        return true;
    }
    // 原有初始化代码...
    isInitialized = true;
    return rc == 0;
}
  1. 使用动态客户端ID
    让Mosquitto自动生成唯一客户端ID,避免冲突:
mMosq = mosquitto_new(NULL, true, NULL);
  1. 正确管理客户端生命周期
    重新初始化前先销毁旧实例:
bool MosquittoAppServer::InitMosquitto() {
    if (mMosq != NULL) {
        mosquitto_loop_stop(mMosq, true);
        mosquitto_destroy(mMosq);
        mMosq = NULL;
    }
    // 原有初始化代码...
}
  1. 检查重连逻辑
    若on_connect回调中存在重连代码,需添加状态判断,仅在连接失败时触发重连,并设置合理的重连间隔,避免频繁连接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 04:25:00