天天看點

TCP的TIME_WAIT狀态[轉]

我發現有個公司面試的時候問了對TCP協定比較細節的地方,那就寫一下幫助自己加深了解和記憶。在開始說TIME_WAIT狀态之前,要知道TCP協定是如何關閉連接配接的。

很多人對TCP協定的三次握手都很熟悉(不知道的可以參考我以前的文章),因為學校的垃圾考試都愛考三次握手,但是很多知道三次握手的人都對TCP協定是如何關閉連接配接不了解。不說廢話了,TCP關閉連接配接過程如下圖,寡人用photoshop畫的,湊合看一下:

TCP的TIME_WAIT狀态[轉]

為了友善描述,我給這個TCP連接配接的一端起名為Client,給另外一端起名為Server。上圖描述的是Client主動關閉的過程,FTP協定中就這樣的。如果要描述Server主動關閉的過程,隻要交換描述過程中的Server和Client就可以了,HTTP協定就是這樣的。

描述過程:

Client調用close()函數,給Server發送FIN,請求關閉連接配接;Server收到FIN之後給Client傳回确認ACK,同時關閉讀通道(不清楚就去看一下shutdown和close的差别),也就是說現在不能再從這個連接配接上讀取東西,現在read傳回0。此時Server的TCP狀态轉化為CLOSE_WAIT狀态。

Client收到對自己的FIN确認後,關閉 寫通道,不再向連接配接中寫入任何資料。

接下來Server調用close()來關閉連接配接,給Client發送FIN,Client收到後給Server回複ACK确認,同時Client關閉讀通道,進入TIME_WAIT狀态。

Server接收到Client對自己的FIN的确認ACK,關閉寫通道,TCP連接配接轉化為CLOSED,也就是關閉連接配接。

Client在TIME_WAIT狀态下要等待最大資料段生存期的兩倍,然後才進入CLOSED狀态,TCP協定關閉連接配接過程徹底結束。

以上就是TCP協定關閉連接配接的過程,現在說一下TIME_WAIT狀态。

從上面可以看到,主動發起關閉連接配接的操作的一方将達到TIME_WAIT狀态,而且這個狀态要保持Maximum Segment Lifetime的兩倍時間。為什麼要這樣做而不是直接進入CLOSED狀态?

原因有二:

一、保證TCP協定的全雙工連接配接能夠可靠關閉

二、保證這次連接配接的重複資料段從網絡中消失

先說第一點,如果Client直接CLOSED了,那麼由于IP協定的不可靠性或者是其它網絡原因,導緻Server沒有收到Client最後回複的ACK。那麼Server就會在逾時之後繼續發送FIN,此時由于Client已經CLOSED了,就找不到與重發的FIN對應的連接配接,最後Server就會收到RST而不是ACK,Server就會以為是連接配接錯誤把問題報告給高層。這樣的情況雖然不會造成資料丢失,但是卻導緻TCP協定不符合可靠連接配接的要求。是以,Client不是直接進入CLOSED,而是要保持TIME_WAIT,當再次收到FIN的時候,能夠保證對方收到ACK,最後正确的關閉連接配接。

再說第二點,如果Client直接CLOSED,然後又再向Server發起一個新連接配接,我們不能保證這個新連接配接與剛關閉的連接配接的端口号是不同的。也就是說有可能新連接配接和老連接配接的端口号是相同的。一般來說不會發生什麼問題,但是還是有特殊情況出現:假設新連接配接和已經關閉的老連接配接端口号是一樣的,如果前一次連接配接的某些資料仍然滞留在網絡中,這些延遲資料在建立新連接配接之後才到達Server,由于新連接配接和老連接配接的端口号是一樣的,又因為TCP協定判斷不同連接配接的依據是socket pair,于是,TCP協定就認為那個延遲的資料是屬于新連接配接的,這樣就和真正的新連接配接的資料包發生混淆了。是以TCP連接配接還要在TIME_WAIT狀态等待2倍MSL,這樣可以保證本次連接配接的所有資料都從網絡中消失。

各種協定都是前人千錘百煉後得到的标準,規範。從細節中都能感受到精巧和嚴謹。每次深入都有同一個感覺,精妙。

轉載于:https://www.cnblogs.com/chllovegeyuting/archive/2012/09/11/2680733.html

繼續閱讀