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

ESP32 LwIP栈UDP广播sendto()返回errno5 I/O错误问题

ESP32 LwIP环境下UDP广播sendto返回errno 5(I/O错误)排查

问题背景

  • 运行硬件:ESP32
  • 使用IP协议栈:LwIP
  • 现象:实现UDP广播发送功能时,socket()、setsockopt()接口调用均返回成功,但执行sendto()时触发errno 5(I/O错误),当前测试代码已移除所有错误检查逻辑。

初始测试代码

static int iobAnnounce;
const char broadcastEnable = 1;
struct sockaddr_in servaddrAnnounce;
char udp_data[22];
int err;

iobAnnounce = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    
setsockopt(iobAnnounce, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable));

memset(&servaddrAnnounce, 0, sizeof(servaddrAnnounce));
servaddrAnnounce.sin_family = AF_INET;
servaddrAnnounce.sin_port = htons(30303);
servaddrAnnounce.sin_addr.s_addr = htonl(INADDR_BROADCAST);

sendto(iobAnnounce,
       udp_data,
       22,
       0,
       (const struct sockaddr *) &servaddrAnnounce,
       sizeof(servaddrAnnounce));

调整记录

最初尝试将全局广播地址INADDR_BROADCAST替换为子网定向广播地址,修改代码如下:

err = tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info); // ESP IDF 接口调用
uint32_t subnetBroadcast = ip_info.ip.addr | ~(ip_info.netmask.addr);
servaddrAnnounce.sin_addr.s_addr = (subnetBroadcast);

修改后问题没有改善,后续对tcpip_adapter_get_ip_info()返回的地址执行htonl()字节序转换,依然报相同错误。调试阶段打印的运行信息如下:

I (5354) IOB: iob_task(): tcpip_adapter_get_ip_info() returned ip d456a8c0; netmask 00ffffff; gateway 0156a8c0.
I (5364) IOB: iob_task(): subnetBroadcast is ff56a8c0.
I (5374) IOB: iob_task(): servaddrAnnounce.sin_addr.s_addr is c0a856ff.

排查修复点

从打印信息来看,子网广播地址计算正确(c0a856ff对应192.168.86.255,和IP、子网掩码匹配),问题出在以下几个常见易忽略的点:

  • SO_BROADCAST参数类型错误:代码中定义broadcastEnable为char类型,但POSIX标准要求SO_BROADCAST的选项参数为int类型。部分版本LwIP不会严格校验setsockopt的参数长度,仅拷贝传入长度的字节数,会出现接口返回成功但实际内核未读取到正确值、广播发送权限未开启的情况,需要将参数修改为const int broadcastEnable = 1;,同时传入长度设置为sizeof(broadcastEnable)。
  • 发送时机过早:tcpip_adapter_get_ip_info()能读到IP信息不代表LwIP路由表已经完成更新、链路完全就绪,如果在收到SYSTEM_EVENT_STA_GOT_IP事件后立刻调用发送,可能出现路由查找失败返回I/O错误,可以在发送前增加100ms左右延时,或在链路就绪事件回调中触发广播发送。
  • LwIP配置未开启广播支持:检查ESP-IDF的menuconfig配置,确认LWIP_SO_BROADCAST选项已开启,若该选项关闭,SO_BROADCAST设置不会生效,所有广播包发送都会被拒绝。
  • 全局广播场景未绑定出接口:如果使用INADDR_BROADCAST(255.255.255.255)全局广播地址,需要先调用bind()将socket绑定到STA接口的本地IP,否则LwIP无法选定发送出接口,会返回发送错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 02:09:18