找回密码
 立即注册
首页 业界区 业界 LWIP TCP滑动窗口为TCP ZeroWindow的解决方法

LWIP TCP滑动窗口为TCP ZeroWindow的解决方法

殳世英 6 小时前
最近做项目使用到LWIP, 板子当作客户端,PC机当作服务器,当板子和PC机通信一段时间后,板子就接收不到数据。抓包分析为:
1.png

发现经过一段时间通信后,滑动窗口大小越来越小,最终显示为TCP WINDOW FULL,TCP ZeroWindow。 仔细分析了下LWIP源码,还以为是内存管理出了问题,跟踪了半天memp.c也没发现问题。后来发现问题出现自己的应用实现代码,下面是我这边的实现代码:
  1. err_t tcp_client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
  2. {
  3.     if (err != ERR_OK) {
  4.         RLOG_ERROR("Error in tcp_client_recv: %d\n", err);
  5.         tcp_client_close(tpcb); // 关闭连接
  6.         return ERR_OK; // 释放 pbuf
  7.     }
  8.     if (p != NULL) {
  9.         // 处理接收到的数据
  10.         char *data = (char *)p->payload;
  11.         int datalen = p->len;
  12.         // 安全地复制数据
  13.         char buff[datalen + 1];
  14.         memcpy(buff, data, datalen);
  15.         buff[datalen] = '\0';
  16.         // 打印接收到的数据
  17.         //RLOG_INFO("Received data: %s\n", buff);
  18.         // 释放 pbuf
  19.         pbuf_free(p);
  20.         RLOG_INFO("pbuf freed\n");
  21.     }
  22.     tcp_output(tpcb);
  23.     return ERR_OK;
  24. }
复制代码
上面的代码,需要在接受数据后,主动调用tcp_recved(tpcb, p->tot_len) ,修改代码后,再次验证功能正常。
修改后的代码:
  1. err_t tcp_client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
  2. {
  3.     if (err != ERR_OK) {
  4.         RLOG_ERROR("Error in tcp_client_recv: %d\n", err);
  5.         tcp_client_close(tpcb); // 关闭连接
  6.         return ERR_OK; // 释放 pbuf
  7.     }
  8.     if (p != NULL) {
  9.         // 处理接收到的数据
  10.         char *data = (char *)p->payload;
  11.         int datalen = p->len;
  12.         // 安全地复制数据
  13.         char buff[datalen + 1];
  14.         memcpy(buff, data, datalen);
  15.         buff[datalen] = '\0';
  16.         // 打印接收到的数据
  17.         //RLOG_INFO("Received data: %s\n", buff);
  18.                
  19.         tcp_recved(tpcb, p->tot_len);
  20.         // 释放 pbuf
  21.         pbuf_free(p);
  22.         RLOG_INFO("pbuf freed\n");
  23.     }
  24.     tcp_output(tpcb);
  25.     return ERR_OK;
  26. }
复制代码
原来,tcp_recved(tpcb, p->tot_len) 的主要作用是通知 TCP 层应用程序已经处理了指定长度的数据。这有助于 TCP 层调整接收窗口,避免接收缓冲区溢出,并确保数据传输的高效性。如果忘记调用这个函数,可能会导致接收窗口过小,影响数据传输效率。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册