TCP兩個重要窗口
滑動窗口
滑動窗口是 接受數據 端使用的窗口大小,用來告知發送端接收端的緩存大小,以此可以控制發送端發送數據的大小,從而達到流量控制的目的,對應==>rwnd:接收端窗口(receiver window)
對于流量控制,是一個端對端的概念。由接收端返回的rwnd控制。
擁塞窗口
那么對于數據的 發送數據 端就是擁塞窗口,擁塞窗口不代表緩存,擁塞窗口指某一源端數據流在一個RTT內可以最多發送的 數據包 數,cwnd:發送端窗口( congestion window )。
發送端數據結構
為了保證順序性,每?個包都有?個ID。在建?連接的時候,會商定起始的ID是什么,然后 按照ID?個個發送。為了保證不丟包,對于發送的包都要進?應答,但是這個應答也不是?個?個來的,?是會應答某個之前 的ID,表示都收到了,這種模式稱為累計確認或者累計應答(cumulative acknowledgment)。 為了記錄所有發送的包和接收的包,TCP也需要發送端和接收端分別都有緩存來保存這些記錄。發送端的緩存?是按照包的ID ?個個排列,根據處理的情況分成四個部分。 第?部分:發送了并且已經確認的。這部分就是你交代下屬的,并且也做完了的,應該劃掉的。 第?部分:發送了并且尚未確認的。這部分是你交代下屬的,但是還沒做完的,需要等待做完的回復之后,才能劃掉。 第三部分:沒有發送,但是已經等待發送的。這部分是你還沒有交代給下屬,但是?上就要交代的。 第四部分:沒有發送,并且暫時還不會發送的。這部分是你還沒有交代給下屬,?且暫時還不會交代給下屬的。 在TCP?,接收端會給發送端報?個窗?的??,叫Advertised window。這個窗 ?的??應該等于上?的第?部分加上第三部分,就是已經交代了沒做完的加上?上要交代的。超過這個窗?的,接收端做不 過來,就不能發送了。 于是,發送端需要保持下?的數據結構。
LastByteAcked:第?部分和第?部分的分界線 LastByteSent:第?部分和第三部分的分界線 LastByteAcked + AdvertisedWindow:第三部分和第四部分的分界線 對于接收端來講,它的緩存?記錄的內容要簡單?些。
擁塞控制和流量控制的區別
擁塞控制:擁塞控制是作用于網絡的,它是防止過多的數據注入到網絡中,避免出現網絡負載過大的情況;常用的方法就是:
- 慢開始、擁塞避免
- 快重傳、快恢復
流量控制:流量控制是作用于接收者的,它是控制發送者的發送速度從而使接收者來得及接收,防止分組丟失的。
接收端數據結構
第?部分:接受并且確認過的。也就是我領導交代給我,并且我做完的。 第?部分:還沒接收,但是?上就能接收的。也即是我??的能夠接受的最??作量。 第三部分:還沒接收,也沒法接收的。也即超過?作量的部分,實在做不完。 對應的數據結構就像這樣。

MaxRcvBuffer:最?緩存的量; LastByteRead之后是已經接收了,但是還沒被應?層讀取的; NextByteExpected是第?部分和第?部分的分界線。 第?部分的窗?有多?呢? NextByteExpected和LastByteRead的差其實是還沒被應?層讀取的部分占?掉的MaxRcvBuffer的量,我們定義為A。 AdvertisedWindow其實是MaxRcvBuffer減去A。 也就是:AdvertisedWindow=MaxRcvBuffer-((NextByteExpected-1)-LastByteRead)。 那第?部分和第三部分的分界線在哪?呢?NextByteExpected加AdvertisedWindow就是第?部分和第三部分的分界線,其實 也就是LastByteRead加上MaxRcvBuffer。 其中第?部分??,由于受到的包可能不是順序的,會出現空擋,只有和第?部分連續的,可以?上進?回復,中間空著的部 分需要等待,哪怕后?的已經來了。
流量控制
如何控制
接收方每次收到數據包,可以在發送確定報文的時候,同時告訴發送方自己的緩存區還剩余多少是空閑的,我們也把緩存區的剩余大小稱之為接收窗口大小,用變量win來表示接收窗口的大小。
發送方收到之后,便會調整自己的發送速率,也就是調整自己發送窗口的大小,當發送方收到接收窗口的大小為0時,發送方就會停止發送數據,防止出現大量丟包情況的發生。
發送方何時再繼續發送數據
當發送方停止發送數據后,該怎樣才能知道自己可以繼續發送數據?
我們可以采用這樣的策略:當接收方處理好數據,接受窗口 win > 0 時,接收方發個通知報文去通知發送方,告訴他可以繼續發送數據了。當發送方收到窗口大于0的報文時,就繼續發送數據。
不過這時候可能會遇到一個問題,假如接收方發送的通知報文,由于某種網絡原因,這個報文丟失了,這時候就會引發一個問題:接收方發了通知報文后,繼續等待發送方發送數據,而發送方則在等待接收方的通知報文,此時雙方會陷入一種僵局。
為了解決這種問題,我們采用了另外一種策略:當發送方收到接受窗口 win = 0 時,這時發送方停止發送報文,并且同時開啟一個定時器,每隔一段時間就發個測試報文去詢問接收方,打聽是否可以繼續發送數據了,如果可以,接收方就告訴他此時接受窗口的大小;如果接受窗口大小還是為0,則發送方再次刷新啟動定時器。
擁塞控制的算法
我們在開始假定:
- 數據是單方向傳遞,另一個窗口只發送確認;
- 接收方的緩存足夠大,因此發送方的大小的大小由網絡的擁塞程度來決定。
慢開始算法:
cwnd的大小取決于網絡的擁塞程度,并且動態地在變化。發送方讓自己的發送窗口等于擁塞窗口,另外考慮到接受方的接收能力,發送窗口可能小于擁塞窗口。
慢開始算法的思路就是,不要一開始就發送大量的數據,先探測一下網絡的擁塞程度,也就是說由小到大逐漸增加擁塞窗口的大小。
這里用報文段的個數作為擁塞窗口的大小舉例說明慢開始算法,實際的擁塞窗口大小是以字節為單位的。
一個傳輸輪次所經歷的時間其實就是往返時間RTT,而且沒經過一個傳輸輪次(transmission round),擁塞窗口cwnd就加倍。
為了防止cwnd增長過大引起網絡擁塞,還需設置一個慢開始門限ssthresh狀態變量。ssthresh的用法如下:當cwnd<ssthresh時,使用慢開始算法。 當cwnd>ssthresh時,改用擁塞避免算法。 當cwnd=ssthresh時,慢開始與擁塞避免算法任意
注意,這里的“慢”并不是指cwnd的增長速率慢,而是指在TCP開始發送報文段時先設置cwnd=1,然后逐漸增大,這當然比按照大的cwnd一下子把許多報文段突然注入到網絡中要“慢得多”。
擁塞避免算法
擁塞避免算法讓擁塞窗口緩慢增長,即每經過一個往返時間RTT就把發送方的擁塞窗口cwnd加1,而不是加倍。這樣擁塞窗口按線性規律緩慢增長。
無論是在慢開始階段還是在擁塞避免階段,只要發送方判斷網絡出現擁塞(其根據就是沒有按時收到確認,雖然沒有收到確認可能是其他原因的分組丟失,但是因為無法判定,所以都當做擁塞來處理),就把慢開始門限ssthresh設置為出現擁塞時的發送窗口大小的一半(但不能小于2)。然后把擁塞窗口cwnd重新設置為1,執行慢開始算法。這樣做的目的就是要迅速減少主機發送到網絡中的分組數,使得發生擁塞的路由器有足夠時間把隊列中積壓的分組處理完畢。
- 擁塞窗口cwnd初始化為1個報文段,慢開始門限初始值為16
- 執行慢開始算法,指數規律增長到第4輪,即cwnd=16=ssthresh,改為執行擁塞避免算法,擁塞窗口按線性規律增長
- 假定cwnd=24時,網絡出現超時(擁塞),則更新后的ssthresh=12,cwnd重新設置為1,并執行慢開始算法。當cwnd=12=ssthresh時,改為執行擁塞避免算法
乘法減小(Multiplicative Decrease)和加法增大(Additive Increase)
“乘法減小”指的是無論是在慢開始階段還是在擁塞避免階段,只要發送方判斷網絡出現擁塞,就把慢開始門限ssthresh設置為出現擁塞時的發送窗口大小的一半,并執行慢開始算法,所以當網絡頻繁出現擁塞時,ssthresh下降的很快,以大大減少注入到網絡中的分組數。“加法增大”是指執行擁塞避免算法后,使擁塞窗口緩慢增大,以防止過早出現擁塞。常合起來成為AIMD算法。
注意:“擁塞避免”并非完全能夠避免了阻塞,而是使網絡比較不容易出現擁塞。
TCP兩個重要窗口
滑動窗口
滑動窗口是接受數據端使用的窗口大小,用來告知發送端接收端的緩存大小,以此可以控制發送端發送數據的大小,從而達到流量控制的目的,對應==>rwnd:接收端窗口(receiver window)
對于流量控制,是一個端對端的概念。由接收端返回的rwnd控制。
擁塞窗口
那么對于數據的發送數據端就是擁塞窗口,擁塞窗口不代表緩存,擁塞窗口指某一源端數據流在一個RTT內可以最多發送的 數據包 數,cwnd:發送端窗口( congestion window )。
發送端數據結構
為了保證順序性,每?個包都有?個ID。在建?連接的時候,會商定起始的ID是什么,然后 按照ID?個個發送。為了保證不丟包,對于發送的包都要進?應答,但是這個應答也不是?個?個來的,?是會應答某個之前 的ID,表示都收到了,這種模式稱為累計確認或者累計應答(cumulative acknowledgment)。 為了記錄所有發送的包和接收的包,TCP也需要發送端和接收端分別都有緩存來保存這些記錄。發送端的緩存?是按照包的ID ?個個排列,根據處理的情況分成四個部分。第?部分:發送了并且已經確認的。這部分就是你交代下屬的,并且也做完了的,應該劃掉的。第?部分:發送了并且尚未確認的。這部分是你交代下屬的,但是還沒做完的,需要等待做完的回復之后,才能劃掉。第三部分:沒有發送,但是已經等待發送的。這部分是你還沒有交代給下屬,但是?上就要交代的。第四部分:沒有發送,并且暫時還不會發送的。這部分是你還沒有交代給下屬,?且暫時還不會交代給下屬的。在TCP?,接收端會給發送端報?個窗?的??,叫Advertised window。這個窗 ?的??應該等于上?的第?部分加上第三部分,就是已經交代了沒做完的加上?上要交代的。超過這個窗?的,接收端做不 過來,就不能發送了。于是,發送端需要保持下?的數據結構。
LastByteAcked:第?部分和第?部分的分界線 LastByteSent:第?部分和第三部分的分界線 LastByteAcked + AdvertisedWindow:第三部分和第四部分的分界線 對于接收端來講,它的緩存?記錄的內容要簡單?些。
擁塞控制和流量控制的區別
擁塞控制:擁塞控制是作用于網絡的,它是防止過多的數據注入到網絡中,避免出現網絡負載過大的情況;常用的方法就是:
- 慢開始、擁塞避免
- 快重傳、快恢復
流量控制:流量控制是作用于接收者的,它是控制發送者的發送速度從而使接收者來得及接收,防止分組丟失的。
接收端數據結構
第?部分:接受并且確認過的。也就是我領導交代給我,并且我做完的。第?部分:還沒接收,但是?上就能接收的。也即是我??的能夠接受的最??作量。第三部分:還沒接收,也沒法接收的。也即超過?作量的部分,實在做不完。對應的數據結構就像這樣。
MaxRcvBuffer:最?緩存的量; LastByteRead之后是已經接收了,但是還沒被應?層讀取的; NextByteExpected是第?部分和第?部分的分界線。 第?部分的窗?有多?呢?NextByteExpected和LastByteRead的差其實是還沒被應?層讀取的部分占?掉的MaxRcvBuffer的量,我們定義為A。 AdvertisedWindow其實是MaxRcvBuffer減去A。 也就是:AdvertisedWindow=MaxRcvBuffer-((NextByteExpected-1)-LastByteRead)。 那第?部分和第三部分的分界線在哪?呢?NextByteExpected加AdvertisedWindow就是第?部分和第三部分的分界線,其實 也就是LastByteRead加上MaxRcvBuffer。 其中第?部分??,由于受到的包可能不是順序的,會出現空擋,只有和第?部分連續的,可以?上進?回復,中間空著的部 分需要等待,哪怕后?的已經來了。
流量控制
如何控制
接收方每次收到數據包,可以在發送確定報文的時候,同時告訴發送方自己的緩存區還剩余多少是空閑的,我們也把緩存區的剩余大小稱之為接收窗口大小,用變量win來表示接收窗口的大小。
發送方收到之后,便會調整自己的發送速率,也就是調整自己發送窗口的大小,當發送方收到接收窗口的大小為0時,發送方就會停止發送數據,防止出現大量丟包情況的發生。
640830×573
發送方何時再繼續發送數據
當發送方停止發送數據后,該怎樣才能知道自己可以繼續發送數據?
我們可以采用這樣的策略:當接收方處理好數據,接受窗口 win > 0 時,接收方發個通知報文去通知發送方,告訴他可以繼續發送數據了。當發送方收到窗口大于0的報文時,就繼續發送數據。
不過這時候可能會遇到一個問題,假如接收方發送的通知報文,由于某種網絡原因,這個報文丟失了,這時候就會引發一個問題:接收方發了通知報文后,繼續等待發送方發送數據,而發送方則在等待接收方的通知報文,此時雙方會陷入一種僵局。
為了解決這種問題,我們采用了另外一種策略:當發送方收到接受窗口 win = 0 時,這時發送方停止發送報文,并且同時開啟一個定時器,每隔一段時間就發個測試報文去詢問接收方,打聽是否可以繼續發送數據了,如果可以,接收方就告訴他此時接受窗口的大小;如果接受窗口大小還是為0,則發送方再次刷新啟動定時器。
640867×696
擁塞控制的算法
我們在開始假定:
- 數據是單方向傳遞,另一個窗口只發送確認;
- 接收方的緩存足夠大,因此發送方的大小的大小由網絡的擁塞程度來決定。
慢開始算法:
cwnd的大小取決于網絡的擁塞程度,并且動態地在變化。發送方讓自己的發送窗口等于擁塞窗口,另外考慮到接受方的接收能力,發送窗口可能小于擁塞窗口。
慢開始算法的思路就是,不要一開始就發送大量的數據,先探測一下網絡的擁塞程度,也就是說由小到大逐漸增加擁塞窗口的大小。
這里用報文段的個數作為擁塞窗口的大小舉例說明慢開始算法,實際的擁塞窗口大小是以字節為單位的。
一個傳輸輪次所經歷的時間其實就是往返時間RTT,而且沒經過一個傳輸輪次(transmission round),擁塞窗口cwnd就加倍。
為了防止cwnd增長過大引起網絡擁塞,還需設置一個慢開始門限ssthresh狀態變量。ssthresh的用法如下:當cwnd<ssthresh時,使用慢開始算法。當cwnd>ssthresh時,改用擁塞避免算法。當cwnd=ssthresh時,慢開始與擁塞避免算法任意
注意,這里的“慢”并不是指cwnd的增長速率慢,而是指在TCP開始發送報文段時先設置cwnd=1,然后逐漸增大,這當然比按照大的cwnd一下子把許多報文段突然注入到網絡中要“慢得多”。
擁塞避免算法
擁塞避免算法讓擁塞窗口緩慢增長,即每經過一個往返時間RTT就把發送方的擁塞窗口cwnd加1,而不是加倍。這樣擁塞窗口按線性規律緩慢增長。
無論是在慢開始階段還是在擁塞避免階段,只要發送方判斷網絡出現擁塞(其根據就是沒有按時收到確認,雖然沒有收到確認可能是其他原因的分組丟失,但是因為無法判定,所以都當做擁塞來處理),就把慢開始門限ssthresh設置為出現擁塞時的發送窗口大小的一半(但不能小于2)。然后把擁塞窗口cwnd重新設置為1,執行慢開始算法。這樣做的目的就是要迅速減少主機發送到網絡中的分組數,使得發生擁塞的路由器有足夠時間把隊列中積壓的分組處理完畢。
- 擁塞窗口cwnd初始化為1個報文段,慢開始門限初始值為16
- 執行慢開始算法,指數規律增長到第4輪,即cwnd=16=ssthresh,改為執行擁塞避免算法,擁塞窗口按線性規律增長
- 假定cwnd=24時,網絡出現超時(擁塞),則更新后的ssthresh=12,cwnd重新設置為1,并執行慢開始算法。當cwnd=12=ssthresh時,改為執行擁塞避免算法
乘法減小(Multiplicative Decrease)和加法增大(Additive Increase)
“乘法減小”指的是無論是在慢開始階段還是在擁塞避免階段,只要發送方判斷網絡出現擁塞,就把慢開始門限ssthresh設置為出現擁塞時的發送窗口大小的一半,并執行慢開始算法,所以當網絡頻繁出現擁塞時,ssthresh下降的很快,以大大減少注入到網絡中的分組數。“加法增大”是指執行擁塞避免算法后,使擁塞窗口緩慢增大,以防止過早出現擁塞。常合起來成為AIMD算法。
注意:“擁塞避免”并非完全能夠避免了阻塞,而是使網絡比較不容易出現擁塞。
長肥管道
一個連接的時延帶寬積可表示為:capacity(b)=bandwidth(b/s)×round-triptime(s)。也可稱它為兩端的管道大小。具有大的帶寬時延乘積的網絡被稱為長肥網絡(LongFatNetwork,即LFN),而一個運行在LFN上的TCP連接被稱為長肥管道。使用長肥管道會遇到多種問題。
- TCP首部中窗口大小為16bit,因此窗口大小最大為65535字節,這就將發送方發送但未被確認的數據的總長度限制到了65536字節。對于LFN管道,這可能會出現所有的數據都還未到達接收方,但是發送方已受限于窗口大小而不能繼續發送的情形,這就極大的降低了網絡的吞吐量。擴大窗口選項可以解決這個問題。
- 根據TCP的擁塞控制,丟失分組會導致連接進行擁塞控制,即便是由于冗余ACK而進入了快速恢復,也會使得擁塞窗口降低一半,而如果是由于超時進入了慢啟動,則擁塞窗口會變為1,無論是哪一種情形,發送方允許被發送的數據量都大量減小了,這會導致網絡吞吐量降低。選擇確認(SACK)可以用來部分避免該問題,采用該技術使得接收方可以有選擇的對無序到達的報文段進行確認而不是采用累積確認,這樣被確認的報文段就不會超時,也不會有冗余的ACK。
- TCP并不對每個報文段進行RTT測量。在一個長肥網絡LFN上需要更好的RTT測量機制。
- TCP對每個字節數據使用一個32bit無符號的序號來進行標識。TCP定義了最大的報文段生存時間(MSL)來限制報文段在網絡中的生存時間。但是在LFN網絡上,由于序號空間是有限的,在已經傳輸了4294967296個字節以后序號會被重用。如果網絡快到在不到一個MSL的時候序號就發生了回繞,網絡中就會有兩個具有相同序號的不同的報文段,接收方將無法區分它們的順序。在一個千兆比特網絡(1000Mb/s)中只需要34秒就可以完成4294967296個字節的發送。使用TCP的時間戳選項的PAWS(ProtectionAgainstWrappedSequencenumbers)算法(保護回繞的序號)可以解決該問題。
快重傳算法:
快重傳要求接收方在收到一個失序的報文段后就立即發出重復確認(為的是使發送方及早知道有報文段沒有到達對方,可提高網絡吞吐量約20%)而不要等到自己發送數據時捎帶確認。快重傳算法規定,發送方只要一連收到三個重復確認就應當立即重傳對方尚未收到的報文段,而不必繼續等待設置的重傳計時器時間到期。如下圖:
SACK 方法
另外一種更好的方式叫:Selective Acknowledgment (SACK)(參看RFC 2018),這種方式需要在TCP頭里加一個SACK的東西,ACK還是Fast Retransmit的ACK,SACK則是匯報收到的數據碎版。參看下圖:
這樣,在發送端就可以根據回傳的SACK來知道哪些數據到了,哪些沒有到。于是就優化了Fast Retransmit的算法。當然,這個協議需要兩邊都支持。在 linux下,可以通過tcp_sack參數打開這個功能(Linux 2.4后默認打開)。
這里還需要注意一個問題——接收方Reneging,所謂Reneging的意思就是接收方有權把已經報給發送端SACK里的數據給丟了。這樣干是不被鼓勵的,因為這個事會把問題復雜化了,但是,接收方這么做可能會有些極端情況,比如要把內存給別的更重要的東西。所以,發送方也不能完全依賴SACK,還是要依賴ACK,并維護Time-Out,如果后續的ACK沒有增長,那么還是要把SACK的東西重傳,另外,接收端這邊永遠不能把SACK的包標記為Ack。
注意:SACK會消費發送方的資源,試想,如果一個攻擊者給數據發送方發一堆SACK的選項,這會導致發送方開始要重傳甚至遍歷已經發出的數據,這會消耗很多發送端的資源。詳細的東西請參看《TCP SACK的性能權衡》。
TCP四大定時器
重傳定時器
重傳定時器是用來計算TCP報文段的超時重傳時間的(至于超時重傳時間的確定,這里涉及到一大堆的算法,我這里不細談了)。每發送一個報文段就會啟動重傳定時器,如果在定時器時間到后還沒收到對該報文段的確認,就重傳該報文段,并將重傳定時器復位,重新計算;如果在規定時間內收到了對該報文段的確認,則撤銷該報文段的重傳定時器。
堅持定時器
專門為對付零窗口通知而設立的。
主要是為了應付零窗口大小通知可能導致的死鎖問題。如果接收端在向發送端發送了零窗口報文段后不久,接收端的接收緩存又有了一些存儲空間,于是接收端向發送端發送了一個非零窗口大小的報文段,然而這個報文段在傳送過程中丟失了,發送端沒有收到該報文段,就一直等待接收端發送非零窗口的報文通知,而接收端并不知道報文段丟失了,而是覺得已經告訴發送端了,就會一直等待發送端發送數據,如果沒有任何措施的話,這話死鎖的局面會一直延續下去。
為了解決這個問題,TCP為每一個連接設有一個堅持定時器(也叫持續計數器)。只要TCP連接的一方收到對方的零窗口通知,就啟動堅持定時器。若堅持定時器設置的時間到期,就發送一個零窗口控測報文段(該報文段只有一個字節的數據,它有一個序號,但該序號永遠不需要確認,因此該序號可以持續重傳),之后會出現以下三種情況:
- 對方在收到探測報文段后,在對該報文段的確認中給出現在的窗口值,如果窗口值仍未零,則收到這個報文段的一方將堅持定時器的值加倍并重啟。堅持計數器最大只能增加到約60秒,在此之后,每次收到零窗口通知,堅持計數器的值就定位60秒。
- 對方在收到探測報文段后,在對該報文段的確認中給出現在的窗口值,如果窗口不為零,那么死鎖的僵局就被打破了。
- 該探測報文發出后,會同時啟動重傳定時器,如果重傳定時器的時間到期,還沒有收到接收到發來的響應,則超時重傳探測報文。
保活定時器
保活定時器是為了應對兩個TCP連接間出現長時間的沒有數據傳輸的情況。如果客戶已與服務器建立了TCP連接,但后來客戶端主機突然故障,則服務器就不能再收到客戶端發來的數據了,而服務器肯定不能這樣永久地等下去,保活定時器就是用來解決這個問題的。服務器每收到一次客戶端的數據,就重新設置保活定時器,通常為2小時,如果2小時沒有收到客戶端的數據,服務端就發送一個探測報文,以后每隔75秒發送一次,如果連續發送10次探測報文段后仍沒有收到客戶端的響應,服務器就認為客戶端出現了故障,就可以終止這個連接。
時間等待計時器(2MSL定時器 )
2MSL定時器測量一個連接處于TIME—WAIT狀態的時間,通常為2MSL(報文段壽命的兩倍)。2MSL定時器的設置主要是為了確保發送的最后一個ACK報文段能夠到達對方,并防止之前與本連接有關的由于延遲等原因而導致已失效的報文被誤判為有效。在連接終止期使用,當TCP關閉連接時,并不認為這個連接就真正關閉了,在時間等待期間,連接還處于一種中間過度狀態。這樣就可以使重復的fin報文段在到達終點后被丟棄。
TIME_WAIT 確保有足夠的時間讓對端收到了ACK,如果被動關閉的那方沒有收到 ACK,就會觸發被動端重發 FIN。因為最后一次確認應答 ACK 報文段很有可能丟失,因而使被動關閉方處于在LIST_ACK 狀態的,此時被動關閉方會重發這個 FIN+ACK 報文段,在這等待的 2MSL 時間內主動關閉方重新收到這個被動關閉方重發的 FIN+ACK 報文段,因此,主動關閉方會重新發送確認應答信息,從而重新啟動 2MSL 計時器,直到通信雙方都進入 CLOSED 狀態。如果主動關閉方在 TIME_WAIT 狀態不等待一段時間就直接釋放連接并進入 CLOSED 狀態,那么主動關閉方無法收到來自被動關閉方重發的 FIN+ACK 報文段,也就不會再發送一次確認 ACK 報文段,因此被動關閉方就無法正常進入CLOSED 狀態。
該定時器使得有足夠的時間讓這個連接不會跟后面的連接混在一起。防止已失效的請求連接出現在本連接中。在連接處于 2MSL 等待時,任何遲到的報文段將被丟棄,因為處于 2MSL等待的、由該插口(插口是IP和端口對的意思,socket)定義的連接在這段時間內將不能被再用,這樣就可以使下一個新的連接中不會出現這種舊的連接之前延遲的報文段。






