Time-wait狀態(2MSL)一些理解


1. 編寫TCP/SOCK 服務時,SO_REUSEADDR到底是什么意思?

這個套接字選項通知內核,如果端口忙,但TCP狀態處於TIME_WAIT,可以重用端口。如果端口忙,TCP狀態處於其他狀態,重用端口時依舊指明“地址已經在使用中”。如果你的服務程序停止后向立刻重啟,而新套接字依舊使用同一個端口,此時SO_REUSEADDR選項非常有用。但是必須意識到,此時任何非期望數據到達,都可能導致服務程序反應混亂。

一個套接字由五個部分組成:協議,本地地址,本地端口,遠程地址和遠程端口。SO_REUSEADDR僅僅表示可以重用本地地址,本地端口。

 

2. 為什么需要TIME_WAIT狀態?

假設最后的ACK丟失,server將重發FIN,client必須維護TCP狀態信息以便可以重發最后的ACK,否則將會發送RST,結果server認為發生錯誤。TCP實現必須可靠地終止連接的兩個方向,所以client必須進入TIME_WAIT狀態。

此外,考慮一種情況,TCP實現可能面臨着先后兩個相同的五元組。如果前一個連接處於TIME_WAIT狀態,而允許另一個擁有相同五元組連接出現,可能處理TCP報文時,兩個連接互相干擾。所以使用SO_REUSEADDR選項就需要考慮這種情況。

 

3. 什么是2MSL

MSL是Maximum Segment Lifetime,譯為“報文最大生存時間”,他是任何報文在網絡上存在的最長時間,超過這個時間報文將被丟棄。
因為TCP報文(segment)是IP數據報(datagram)的數據部分,而IP頭中有一個TTL域,TTL是time to live的縮寫,中文可以譯為“生存時間”,這個生存時間是由源主機設置初始值但不是存的具體時間,而是存儲了一個IP數據報可以經過的最大路由數,每經過一個處理他的路由器此值就減1,當此值為0則數據報將被丟棄,同時發送ICMP報文通知源主機。
RFC 793中規定MSL為2分鍾,實際應用中常用的是30秒,1分鍾和2分鍾等
2MSL即兩倍的MSL,TCP的TIME_WAIT狀態也稱為2MSL等待狀態,當TCP的一端發起主動關閉,在發出最后一個ACK包后,即第3次握手完成后發送了第四次握手的ACK包后就進入了TIME_WAIT狀態,必須在此狀態上停留兩倍的MSL時間。
等待2MSL時間主要目的是怕最后一個ACK包對方沒收到,那么對方在超時后將重發第三次握手的FIN包,主動關閉端接到重發的FIN包后可以再發一個ACK應答包。
在TIME_WAIT狀態時兩端的端口不能使用,要等到2MSL時間結束才可繼續使用。
當連接處於2MSL等待階段時任何遲到的報文段都將被丟棄。不過在實際應用中可以通過設置SO_REUSEADDR選項達到不必等待2MSL時間結束再使用此端口。

TTL與MSL是有關系的但不是簡單的相等的關系,MSL要大於等於TTL。

 

4. 為什么TIME_WAIT狀態需要保持2MSL這么長的時間?

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

 

2MSL等待狀態
TIME_WAIT狀態也稱為2MSL等待狀態。每個具體TCP實現必須選擇一個報文段最大生存時間MSL(Maximum Segment Lifetime)。它是任何報文段被丟棄前在網絡內的最長時間。我們知道這個時間是有限的,因為TCP報文段以IP數據報在網絡內傳輸,而IP數據報則有限制其生存時間的TTL字段。
對一個具體實現所給定的MSL值,處理的原則是:當TCP執行一個主動關閉,並發回最后一個ACK,該連接必須在TIME_WAIT狀態停留的時間為2倍的MSL。這樣可讓TCP再次發送最后的ACK以防這個ACK丟失(另一端超時並重發最后的FIN)。
這種2MSL等待的另一個結果是這個TCP連接在2MSL等待期間,定義這個連接的套接口(客戶的IP地址和端口號,服務器的IP地址和端口號)不能再被使用。這個連接只能在2MSL結束后才能再被使用。遺憾的是,大多數TCP實現(如伯克利版)強加了更為嚴格的限制。在2MSL等待期間,套接口中使用的本地端口在默認情況下不能再被使用。
在連接處於2MSL等待時,任何遲到的報文段將被丟棄。因為處於2MSL等待的、由該套接口對(socket pair)定義的連接在這段時間內不能被再用,因此當要建立一個有效的連接時,來自該連接的一個較早替身( incarnation)的遲到報文段作為新連接的一部分不可能不被曲解(一個連接由一個插口對來定義。一個連接的新的實例( instance)稱為該連接的替身)。
客戶執行主動關閉並進入TIME_WAIT是正常的。服務器通常執行被動關閉,不會進入TIME_WAIT狀態。這暗示如果我們終止一個客戶程序,並立即重新啟動這個客戶程序,則這個新客戶程序將不能重用相同的本地端口。這不會帶來什么問題,因為客戶使用本地端口,而並不關心這個端口號是什么。
然而,對於服務器,情況就有所不同,因為服務器使用熟知端口。如果我們終止一個已經建立連接的服務器程序,並試圖立即重新啟動這個服務器程序,服務器程序將不能把它的這個熟知端口賦值給它的端點,因為那個端口是處於2MSL連接的一部分。在重新啟動服務器程序前,它需要在1~4分鍾。
盡管許多具體的實現中允許一個進程重新使用仍處於2MSL等待的端口(通常是設置選項SO _REUSEADDR),但TCP不能允許一個新的連接建立在相同的插口對上。

平靜時間的概念
對於來自某個連接的較早替身的遲到報文段, 2MSL等待可防止將它解釋成使用相同插口對的新連接的一部分。但這只有在處於2MSL等待連接中的主機處於正常工作狀態時才有效。如果使用處於2MSL等待端口的主機出現故障,它會在MSL秒內重新啟動,並立即使用故障前仍處於2MSL的插口對來建立一個新的連接嗎?如果是這樣,在故障前從這個連接發出而遲到的報文段會被錯誤地當作屬於重啟后新連接的報文段。無論如何選擇重啟后新連接的初始序號,都會發生這種情況。
為了防止這種情況,RFC 793指出TCP在重啟動后的MSL秒內不能建立任何連接。這就稱為平靜時間(quiet time)。只有極少的實現版遵守這一原則,因為大多數主機重啟動的時間都比MSL秒要長。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM