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
相关产品推荐
相关产品推荐

