TIME_WAIT狀態分析

先仍給出一段測試代碼,同CLOSE_WAIT狀態分析一文測試代碼,main函數如下.測試後,會發現兩邊有大量的TIME_WAIT連接.

int main(int argc, char* argv[]){
    int sender = 0;
    int ret    = 0;
    int listen_sock = 0;
    if(argc !=2){
         printf("usage: ./test 1/n");
         return -1;
    }
    sender = atoi(argv[1]);
    if(sender){
       while(1){
           ret = socket_connect("10.224.55.145",8765);
           if(ret < 0){
               return -1;
           }else{
               close(ret);
           }
        }
    }else{
        listen_sock = socket_listen(8765,100);
        if(listen_sock < 0){
           return -1;
       }else{
            while(1){
               ret = socket_accept(listen_sock,NULL);
               if(ret < 0){
                  return -1;
               }else{
                  close(ret);
             }
         }
        }
    }
    return 0;
}


CLOSE_WAIT狀態分析一文已經介紹了一個通常的TCP連接終止的過程.我們以CLIENT端斷開連接重新介紹下:

CLIENT---   FIN  --- SERVER

SERVER---  ACK  --- CLIENT

SERVER---   FIN  --- CLIENT

CLIENT---   ACK --- SERVER

步驟III,SERVER發送FIN報文後進入LAST_ACK狀態.步驟IV,CLIENT接收到FIN報文併發出ACK報文後進入TIME_WAIT狀態.(當SERVER收到ACK報文後,也即可以進入到CLOSED可用狀態了).

 

下面先解釋一下TIME_WAIT狀態存在的原因.
MSL(最大分段生存期)指明TCP報文在Internet上最長生存時間,每個具體的TCP實現都必須選擇一個確定的MSL值.TIME_WAIT 狀態最大保持時間是2*MSL.

TCP報文在傳送過程中可能因爲路由故障被迫緩衝延遲,選擇非最優路徑等等,結果發送方TCP機制開始超時重傳.前一個TCP報文可以稱爲"漫遊TCP重複報文",後一個TCP報文可以稱爲"超時重傳TCP重複報文".假設最終的ACK並未被SERVER端收到,則SERVER端將重發FIN,client必須維護TCP狀態信息以便可以重發最終的ACK,否則會發送RST,然後server認爲發生錯誤.TCP實現必須可靠地終止連接的兩個方向(全雙工關閉),client必須進入TIME_WAIT 狀態,因爲client可能面臨重發最終ACK的情形.

 

如果 TIME_WAIT 狀態保持時間不足夠長(比如小於2MSL),第一個連接就正常終止了, 第二個擁有相同相關五元組的連接出現,而第一個連接的重複報文到達,干擾了第二 個連接.TCP實現必須防止某個連接的重複報文在連接終止後出現,所以讓TIME_WAIT 狀態保持時間足夠長(2MSL),連接相應方向上的TCP報文要麼完全響應完畢,要麼被 丟棄.建立第二個連接的時候,不會混淆.


先調用close()的一方會進入TIME_WAIT狀態.

 

我們寫server程序總是在調用bind()之前設置SO_REUSEADDR套接字選項.這個套接字選項通知內核,如果端口忙,但TCP狀態位於 TIME_WAIT,可以重用端口.如果端口忙,而TCP狀態位於其他狀態,重用端口時依舊得到一個錯誤信息.如果你的服務程序停止後想立即重啓,而新套接字依舊使用同一端口,此時 SO_REUSEADDR 選項非常有用.必須意識到,會出現上面說的問題,當接收到的連接相關五元組的(協議,本地地址,本地端口,遠程地址,遠程端口)相同時,程序有可能收到非期望數據.

 

不過一般的端口分配算法能保證五元組中的遠程端口是不一樣的.客戶端的端口分配一般是自動的,且一般都是從上一次分配的端口號+1開始分配的.所以我們要知道的就是理論上有這種可能,事實上是很不可能.

  

 

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