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狀態連接佔用的端口。

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