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

Mosquitto 2.0.18 MQTTv5初始连接失败后无法自动重连及内存泄漏问题

问题解决方案

一、解决首次连接失败不自动重连的问题

Mosquitto的自动重连机制依赖客户端处于合理的配置状态,你的初始化流程顺序有误,导致内置重连逻辑未生效:

  1. 调整初始化顺序:先完成所有客户端配置(协议版本、用户名密码、回调、重连参数),再启动loop线程,最后发起连接请求。
  2. 移除手动循环连接逻辑:依赖Mosquitto内置的自动重连机制,无需手动重复调用mosquitto_connect_async。

修正后的初始化代码示例:

char sn[64] = {0};
mqtt_prop_sn_get(NULL, sn, sizeof(sn));
g_mosq = mosquitto_new(sn, session, NULL);
if (!g_mosq)
{
    MOCAR_LOG_ERROR("create client fail");
    return -1;
}

// 1. 设置MQTTv5协议版本
mosquitto_int_option(g_mosq, MOSQ_OPT_PROTOCOL_VERSION, MQTT_PROTOCOL_V5);
// 2. 配置用户名密码
mosquitto_username_pw_set(g_mosq, g_mqtt_info.user_id, g_mqtt_info.password);
// 3. 绑定V5版本回调函数
mosquitto_connect_v5_callback_set(g_mosq, my_connect_v5_callback);
mosquitto_message_v5_callback_set(g_mosq, my_message_v5_callback);
mosquitto_subscribe_v5_callback_set(g_mosq, my_subscribe_v5_callback);
mosquitto_disconnect_v5_callback_set(g_mosq, my_disconnect_v5_callback);
// 4. 开启自动重连:初始延迟5秒,最大延迟15秒,启用指数退避
mosquitto_reconnect_delay_set(g_mosq, 5, 15, true);

// 5. 启动loop处理线程
int loop = mosquitto_loop_start(g_mosq);
if (loop != MOSQ_ERR_SUCCESS)
{
    MOCAR_LOG_ERROR_FMT("mosquitto loop error");
    huali_plf_mqtt_cleanup();
    return -1;
}

// 6. 发起异步连接,后续连接失败由loop线程自动触发重连
int ret = mosquitto_connect_async(g_mosq, mqtt_info.address, mqtt_info.port, KEEP_ALIVE);
if (MOSQ_ERR_SUCCESS != ret)
{
    if (MOSQ_ERR_INVAL == ret)
    {
        MOCAR_LOG_DEBUG_FMT("the input parameters were invalid");
        huali_plf_mqtt_cleanup();
        return -1;
    }
    else
    {
        MOCAR_LOG_DEBUG_FMT("initial mqtt connect failed, auto-reconnect will start: %s", mosquitto_strerror(ret));
    }
}

关键说明:

  • Mosquitto的自动重连逻辑在mosquitto_loop_start创建的线程中运行,只要配置了mosquitto_reconnect_delay_set,无论首次连接失败还是后续连接断开,都会按设定策略自动重连。
  • 手动循环调用mosquitto_connect_async会与内置重连机制冲突,应当移除。

二、解决手动重连时的内存泄漏问题

当前手动重连流程频繁启停loop线程是内存泄漏的核心原因——mosquitto_loop_start会创建新线程,频繁操作可能导致线程资源未完全释放。正确做法是保持loop线程持续运行,仅重新发起连接请求:

修正后的重连代码示例:

void mqtt_check_reconnect(void)
{
    if (1 != cv2x_plf_mqtt_get_send_flag())
    {
        // 检查当前连接状态,仅在断开时发起重连
        if (mosquitto_connection_status(g_mosq) != MOSQ_CONN_CONNECTED)
        {
            int rc = mosquitto_reconnect_async(g_mosq);
            if (rc != MOSQ_ERR_SUCCESS)
            {
                MOCAR_LOG_ERROR_FMT("mqtt reconnect failed: %s", mosquitto_strerror(rc));
            }
            else
            {
                MOCAR_LOG_DEBUG_FMT("mqtt reconnect initiated");
            }
        }
    }
}

若需重置参数后重连,也无需重启loop线程,调整为如下流程:

void mqtt_check_reconnect(void)
{
    if (1 != cv2x_plf_mqtt_get_send_flag())
    {
        int rc = 0;
        // 断开当前连接(无需停止loop线程)
        mosquitto_disconnect(g_mosq);
        // 重置用户名密码(按需执行)
        mosquitto_username_pw_set(g_mosq, g_mqtt_info.user_id, g_mqtt_info.password);
        // 重新发起异步连接
        rc = mosquitto_connect_async(g_mosq, mqtt_info.address, mqtt_info.port, KEEP_ALIVE);
        if (rc != MOSQ_ERR_SUCCESS)
        {
            MOCAR_LOG_ERROR_FMT("mqtt reconnect failed: %s", mosquitto_strerror(rc));
        }
    }
}

关键说明:

  • mosquitto_loop_start仅需在初始化时调用一次,后续连接状态变化由该线程自动处理,无需频繁启停。
  • 使用mosquitto_reconnect_async或mosquitto_connect_async发起重连,复用已有loop线程,避免线程资源泄漏。
  • 若问题仍存在,可尝试升级至Mosquitto 2.0.x系列最新稳定版,部分旧版本存在线程资源释放的已知bug。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 06:05:05