LwIP裸机TCP重传由tcp_tmr()定时器驱动,不可手动干预;唯一可控点是sent/err回调,应用需在recv回调中及时调用tcp_recved()更新接收窗口,并周期调用tcp_tmr()以保障重传、窗口更新等机制正常运行。

lwip_tcp_set_flags() 不能直接控制重传,得靠回调和状态机
裸机环境下没有操作系统调度,LwIP 的 TCP 重传完全由其内部定时器驱动(tcp_tmr()),你无法手动触发或取消某次重传。真正能干预的点只有两个:在 sent 回调里确认数据已被对方 ACK,或在 err 回调里感知超时/断连。别试图用 lwip_tcp_set_flags() 或修改 pcb->unacked 链表来“干预重传”——这会破坏 LwIP 内部状态一致性,大概率导致后续 ACK 失效或内存泄漏。
实操建议:
- 在
sent回调中递进更新应用层发送窗口指针,而不是依赖“发完就清空缓冲区” - 若需重发某段业务数据,应重新调用
tcp_write()+tcp_output(),让 LwIP 自行纳入重传队列(注意检查返回值是否为ERR_MEM) - 避免在
sent回调里长时间阻塞或调用复杂计算——裸机无抢占,会拖慢整个 TCP 定时器轮询
接收窗口变化只反映在 pcb->rcv_wnd,但裸机没 recv 回调
LwIP 裸机回调模式下没有类似 POSIX 的 recv() 或事件通知机制,recv 回调(即 tcp_recv_fn)是唯一能感知数据到达和窗口更新的地方。而 pcb->rcv_wnd 的值会在每次收到 ACK 后被 LwIP 自动更新,它代表“还能收多少字节”,但这个值本身不会主动触发回调——只有新数据到达、或对方通过 ACK 暗示窗口扩大时,才可能在下次 recv 回调中体现出来。
常见错误现象:应用层读取完缓冲区后没及时调用 tcp_recved(),导致 pcb->rcv_wnd 一直不涨,对方很快把窗口缩为 0,连接卡死。
立即学习“C++免费学习笔记(深入)”;
实操建议:
- 每次在
recv回调中处理完pbuf数据后,必须立刻调用tcp_recved(pcb, len),len 是实际消费的字节数 - 不要攒着多个
pbuf一起recved——LwIP 不会合并窗口通告,延迟调用等于人为压窗 - 若应用层暂无缓冲区可用,可先调用
tcp_recved(pcb, 0),LwIP 会维持当前窗口不变;等有空间了再收,再recved
裸机必须手动轮询 tcp_tmr(),否则重传和窗口更新全失效
所有 TCP 定时行为——包括 RTO 计算、重传、保活、窗口探测(persist timer)——都依赖周期性调用 tcp_tmr()。裸机无 OS timer tick,如果你没在主循环或硬件定时中断里显式调用它,那么即使对端发了 ACK,本地也不会更新 pcb->snd_wnd;超时重传永远不会发生;连接最终会静默僵死。
性能与兼容性影响:调用间隔太长(如 >500ms)会导致重传延迟激增;太短(如
实操建议:
- 在裸机主循环中以 250ms 为间隔调用一次
tcp_tmr()(LwIP 默认TCP_TMR_INTERVAL即为此值) - 确保该调用不被长延时操作阻塞——比如 SD 卡写入、LCD 刷新等应放在
tcp_tmr()外执行 - 若使用 FreeRTOS 等轻量级 RTOS,也需确认
tcp_tmr()运行在足够高优先级的任务中,避免被业务任务饿死
pcb->snd_wnd 变化不通知你,只能靠 sent 回调+定时轮询推测
发送窗口(pcb->snd_wnd)由对端通告,LwIP 在收到 ACK 段时自动更新它,但不会触发任何回调。裸机环境下,你无法像 Linux 那样用 select() 或 epoll() 监听“窗口变大”,只能被动响应。
容易踩的坑:应用层以为窗口还小,暂停发送;其实对端早已扩窗,只是你没及时发现,白白延长传输时间。
实操建议:
- 在
sent回调中检查pcb->snd_wnd和pcb->snd_buf剩余空间,判断是否可以继续tcp_write() - 若
sent回调未被触发但你知道对端应已 ACK(比如已过 RTO 时间),可主动调用tcp_output(pcb)强制推送当前待发数据,顺便触发窗口状态同步 - 不要依赖
pcb->snd_wnd == 0来做流控决策——它可能因网络延迟暂时为 0,真实窗口早已恢复;更稳妥的是结合发送速率和往返时间估算
裸机 LwIP 的 TCP 行为高度依赖你对定时器、回调时机和状态字段更新节奏的把控。最常被忽略的不是某个 API 怎么用,而是 tcp_tmr() 是否真在跑、tcp_recved() 是否每次收完都立刻调、以及 sent 回调里有没有误判 snd_wnd 的有效性。


















