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

基于lwIP建立MQTT连接出现ERR_RTE路由错误的求助

在STM32F4上使用lwIP 2.1.3建立MQTT连接:绑定TCP与netif后仍无法连接的问题排查与解决

问题回顾

在STM32F4平台使用lwIP 2.1.3稳定版建立MQTT连接时,最初调用mqtt_client_connect()返回ERR_RTE(路由错误)。手动修改mqtt.c的mqtt_client_connect()函数,添加TCP pcb与默认netif的绑定代码,并在tcp.c中实现tcp_bind_to_default_netif()后,路由错误消失,但仍无法连接到MQTT Broker。

用户网络接口配置代码:

lwip_init();
netif_add(&my_netif, &myIP, &maskIP, &gwIP, NULL, netif_init_, netif_input);
netif_set_default(&my_netif);
netif_set_up(&my_netif);

MQTT客户端初始化与连接代码:

mqtt_client = mqtt_client_new();

mqtt_set_inpub_callback(mqtt_client,
        mqtt_incoming_publish_cb,
        mqtt_incoming_data_cb,
        LWIP_CONST_CAST(void*, &mqtt_client_info));

mqtt_client_connect(mqtt_client,
        &mqtt_ip, MQTT_PORT,
        mqtt_connection_cb, LWIP_CONST_CAST(void*, &mqtt_client_info),
        &mqtt_client_info);

手动添加的绑定代码(位于altcp_connect前):

struct tcp_pcb *pcb;
pcb = (struct tcp_pcb *)client->conn->state;
tcp_bind_to_default_netif(pcb);

tcp_bind_to_default_netif()实现:

void tcp_bind_to_default_netif(struct tcp_pcb *pcb){
    LWIP_ASSERT_CORE_LOCKED();
    if (netif_default != NULL) {
        pcb->netif_idx = netif_get_index(netif_default);
    } else {
        pcb->netif_idx = NETIF_NO_INDEX;
    }
}

核心分析

  1. 手动修改lwIP源码的风险:直接修改tcp.c和mqtt.c会破坏lwIP的封装性,后续版本升级时需要重新移植修改,且不符合lwIP的标准使用流程。实际上lwIP提供了标准接口来指定TCP连接使用的netif,无需修改源码。
  2. 路由错误的本质:ERR_RTE通常是lwIP无法找到通往MQTT Broker的路由路径,可能是netif配置错误、路由表未正确生成,或TCP连接未关联到正确的netif。
  3. 连接失败的潜在原因:即使解决了路由错误,TCP握手失败、MQTT协议层错误、Broker配置限制等都可能导致无法建立连接。

解决方案与排查步骤

1. 使用标准方式绑定TCP到指定netif(无需修改lwIP源码)

在调用mqtt_client_connect()之前,通过TCP绑定接口将连接关联到默认netif的本地IP,替代手动修改netif_idx的方式:

mqtt_client = mqtt_client_new();

// 获取TCP pcb
struct tcp_pcb *pcb = (struct tcp_pcb *)mqtt_client->conn->state;
// 绑定到默认netif的本地IP,端口设为0表示自动分配
err_t bind_err = tcp_bind(pcb, &my_netif.ip_addr, 0);
if (bind_err != ERR_OK) {
    // 处理绑定错误
}

// 后续设置回调、发起连接
mqtt_set_inpub_callback(mqtt_client,
        mqtt_incoming_publish_cb,
        mqtt_incoming_data_cb,
        LWIP_CONST_CAST(void*, &mqtt_client_info));

mqtt_client_connect(mqtt_client,
        &mqtt_ip, MQTT_PORT,
        mqtt_connection_cb, LWIP_CONST_CAST(void*, &mqtt_client_info),
        &mqtt_client_info);

这种方式会自动设置TCP pcb的netif_idx,符合lwIP的设计逻辑。

2. 排查基础网络连通性

  • 验证netif配置:确认myIP、maskIP、gwIP的正确性,执行netif_is_up(&my_netif)检查接口是否处于UP状态。
  • 测试路由可达性:如果STM32支持ping功能,尝试ping MQTT Broker的IP;若不支持,可在lwIP中启用LWIP_ICMP并实现ping客户端。
  • 检查网关配置:确认网关IP能正常访问Broker,若Broker不在本地子网,需确保网关正确转发流量。

3. 排查TCP与MQTT协议层问题

  • 检查MQTT连接回调:在mqtt_connection_cb中打印连接状态码,明确是TCP握手失败还是MQTT协议层面的拒绝:
void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status) {
    switch(status) {
        case MQTT_CONNECT_ACCEPTED:
            printf("MQTT连接成功\n");
            break;
        case MQTT_CONNECT_REFUSED_PROTOCOL_VERSION:
            printf("协议版本不被支持\n");
            break;
        case MQTT_CONNECT_REFUSED_IDENTIFIER_REJECTED:
            printf("客户端ID被拒绝\n");
            break;
        case MQTT_CONNECT_REFUSED_SERVER_UNAVAILABLE:
            printf("Broker不可用\n");
            break;
        case MQTT_CONNECT_REFUSED_BAD_USERNAME_PASSWORD:
            printf("用户名/密码错误\n");
            break;
        case MQTT_CONNECT_REFUSED_NOT_AUTHORIZED:
            printf("未授权访问\n");
            break;
        default:
            printf("连接失败,状态码:%d\n", status);
            // 可进一步检查TCP连接状态
            struct tcp_pcb *pcb = (struct tcp_pcb *)client->conn->state;
            printf("TCP pcb状态:%d\n", pcb->state);
            break;
    }
}
  • 确认lwIP配置宏:检查lwipopts.h中是否开启必要的宏:
    • LWIP_TCP = 1
    • LWIP_ALTCP = 1
    • LWIP_ALTCP_TCP = 1
    • MQTT_CLIENT = 1
    • LWIP_ROUTING = 1(若需要跨子网路由)
  • 检查内存资源:确保lwIP的内存池配置足够,比如TCP_PCB_NUM、MQTT_CLIENT_MAX_COUNT等参数设置合理,避免因内存不足导致连接失败。

4. 排查Broker端限制

  • 确认Broker是否允许STM32的IP地址访问,是否开启了对应的MQTT端口(默认1883,若使用TLS则为8883)。
  • 检查客户端ID是否符合Broker要求(比如长度限制、唯一性),用户名和密码是否正确(若Broker启用了认证)。

内容的提问来源于stack exchange,提问作者C.Hicham

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 13:54:55