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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章