1. 程式人生 > >TCP四次揮手後的TIME_WAIT狀態

TCP四次揮手後的TIME_WAIT狀態

首先檢視TCP建立連線與斷開連線的兩對端的狀態圖,如下:
這裡寫圖片描述
由圖可知客戶端在收到服務端的請求斷開連線帶有的FIN位結束報文段,併發送ACK確認以後,其並沒有直接關閉,進入到CLOSED狀態,而是轉變為TIME_WAIT狀態。

  1. TIME_WAIT狀態是做什麼的?
    在這個狀態,顧名思義,即客戶端連線要等待一段長為2MSL(報文段最大生存時間)的時間,才能關閉連線,在標準文件RFC 1122的MSL建議值為2min.
  2. 為什麼存在此狀態?
    (1)可靠的終止TCP的連線:即如上圖,最後客戶端確認伺服器結束報文段6的ACK報文段7若傳輸中丟失,伺服器沒收到確認報文段,則會重發結束報文段,因此客戶端需要停留在此狀態以處理重複收到的結束報文段,從而向伺服器傳送確認報文段。若客戶端此時已經變為closed狀態,它則會以復位報文段來回復伺服器,伺服器則會認為這是一個錯誤。
    (2)保證讓遲來的報文段有足夠的時間被識別丟棄:當一個TCP連線處在TIME_WAIT狀態,它則會依然佔用當前的埠,新的連線時無法立即使用的,但當沒有這個狀態,當立即有新的TCP連線時,其會使用與剛才相同的IP地址與埠號,此時這個新的連線則極有可能收到原來連線的遲到的TCP報文段,這明顯是不應該發生的,所以設定這個狀態是極有必要的。

  3. 為什麼TIME_WAIT狀態要等待2MSL時間?
    由於TCP報文段最大生存時間為MSL,其保持2MSL時間可以確保網路上兩個傳輸方向的尚未接收到的、遲到的報文段都已經消失,或被路由器丟棄,而2MSL時間後建立新的連線其絕不會收到原來連線的應用程式資料。

但在一些情況下,如:一般一個伺服器的IP與埠號是固定的,但若這個伺服器主動關閉連線異常終止,我們此時則需要立即重啟此伺服器,但由於它此時在TIME_WAIT狀態則先會佔著此IP地址與埠號,導致它會重啟失敗,而我們要改變這種情況,可用以下函式解決:

int setsockopt(int sockfd,int level,int optname,const
void* optval,socklen_t optlen); //可如以下如此呼叫: int opt=1; setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

以上SO_REUSEADDR引數可強制程序立即使用處於TIME_WAIT狀態連線佔用的埠。