LWIP tcp服务器,网线不断插拔,服务器不断重连,最后连不上甚至死机

1.STM32芯片,tcp服务器,网线连接时候,客户端不断重连可以正常稳定连接。

 

2.客户端不断重连时候,网线不断断开重连,最后客户端连不上,甚至程序直接死机。

 

通过仿真发现err_t tcp_server_accept(void *arg, struct tcp_pcb *pcb, err_t err),客户端申请连接pcb = NULL,也就是说没有空余的pcb给重连客户端使用,直接仿真tcp_active_pcbs信息发现,pcb->state = FIN_WAIT_1 || FIN_WAIT_2。网线不断断开,pcb关闭4次握手没有实现,只进行一部分,一直等待中。

更改lwip源码不知重哪里下手,也怕改错出现更多bug,只能取巧弄下。

在err_t  tcp_server_accept(void *arg, struct tcp_pcb *pcb, err_t err)函数最前面加个判断,客户端连接分配的pcb为空闲(全被占用了),找到等待关闭pcb全释放了(可能会出现其他问题,不过我这只是单对单使用,能重连上就行)。

         if(pcb == NULL){
                /*网络不稳(不断插拔网线),强制释放pcb*/
                tcp_find_waitPcb();
                printf("MBtcp: accept  pcb == NULL\r\n");
                return ERR_ARG;
            }

 

tcp_find_waitPcb()的函数定义:

void tcp_find_distant(void)
{
    struct tcp_pcb *pcb = NULL;

        for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next)
        {
            if(pcb->state == FIN_WAIT_1 || pcb->state == FIN_WAIT_2){
                tcp_abort( pcb );
            }
        }
}

3.网线稳定,但是客户端不断快速断开连接,出现pcb = pcb->next,进入void tcp_slowtmr(void)函数死循环中出不来了。

 参照:http://www.51hei.com/bbs/dpj-140158-1.html 完美解决问题

 

需改内容
解释
文件名称
添加内容(增加红色字体)
tcp.h
/* the TCP protocol control block */
  struct tcp_pcb {
..............................略......................................
  u8_t pcb_used; 
};
在struct  tcp_pcb 结构体中增加一个字段,pcb_used。这个字段值 = 0 或 = 1。
0代表这个TCP_PCB块没有在使用,已经释放。 
1代表这个TCP_PCB块正在使用,占用内存。
memp.c
void   memp_free(memp_t type, void *mem)
 {
   struct memp *memp;
  
  struct tcp_pcb *pcb;  
  if(type == MEMP_TCP_PCB ){  
      pcb  = (struct tcp_pcb *)mem;
       if(pcb->pcb_used == 0){  
              return;  
       }
       pcb->pcb_used = 0; 
  }
   SYS_ARCH_DECL_PROTECT(old_level);
  ............................略......................................
}
在释放TCP_PCB块的时候,如果pcb_used==0,那么这个TCP_PCB块已经释放过了,可能是没连接的块系统自己释放,也能是自己误操作,多次释放。总之,不管什么原因,已经释放过的不能再释放了,所有这边直接return退出。没有释放的正常释放,只是字段pcb_used置0。
tcp.c
struct tcp_pcb * tcp_alloc(u8_t prio) 
{  ....................略.....................................  
   if (pcb != NULL) {
     ......................略......................................
       pcb->pcb_used = 1;
  }
   return pcb;
}