高級網絡編程之疑症:TCP 的頭號疼症 TIME

TCP 的頭號疼症 TIME_WAIT 狀態

要說明TIME_WAIT的問題,需要解答以下幾個問題。

高級網絡編程之疑症:TCP 的頭號疼症 TIME_WAIT


1Peer兩端,哪一端會進入TIME_WAIT呢?為什麼?

相信大家都知道,TCP主動關閉連接的那一方會最後進入TIME_WAIT。那麼怎麼界定主動關閉方呢?是否主動關閉是由FIN包的先後決定的,就是在自己沒收到對端Peer的FIN包之前自己發出了FIN包,那麼自己就是主動關閉連接的那一方。對於疑症:TCP 的 Peer 兩端同時斷開連接,中描述的情況,那麼Peer兩邊都是主動關閉的一方,兩邊都會進入TIME_WAIT。為什麼是主動關閉的一方進行TIME_WAIT呢,被動關閉的進入TIME_WAIT可以不呢?

我們來看看TCP四次揮手可以簡單分為下面三個過程:

過程一:主動關閉方發送FIN;

過程二:被動關閉方收到主動關閉方的FIN後發送該FIN的ACK,被動關閉方發送FIN;

過程三:主動關閉方收到被動關閉方的FIN後發送該FIN的ACK,被動關閉方等待自己FIN的ACK。

問題就在過程三中,據TCP協議規範,不對ACK進行ACK,如果主動關閉方不進入TIME_WAIT,那麼主動關閉方在發送完ACK就走了的話,如果最後發送的ACK在路由過程中丟掉了,最後沒能到被動關閉方,這個時候被動關閉方沒收到自己FIN的ACK就不能關閉連接,接著被動關閉方會超時重發FIN包,但是這個時候已經沒有對端會給該FIN回ACK,被動關閉方就無法正常關閉連接了,所以主動關閉方需要進入TIME_WAIT以便能夠重發丟掉的被動關閉方FIN的ACK。

2TIME_WAIT狀態是用來解決或避免什麼問題呢?

TIME_WAIT主要是用來解決以下幾個問題:

1)上面解釋為什麼主動關閉方需要進入TIME_WAIT狀態中提到的: 主動關閉方需要進入TIME_WAIT以便能夠重發丟掉的被動關閉方FIN包的ACK。如果主動關閉方不進入TIME_WAIT,那麼在主動關閉方對被動關閉方FIN包的ACK丟失了的時候,被動關閉方由於沒收到自己FIN的ACK,會進行重傳FIN包,這個FIN包到主動關閉方後,由於這個連接已經不存在於主動關閉方了,這個時候主動關閉方無法識別這個FIN包,協議棧會認為對方瘋了,都還沒建立連接你給我來個FIN包?,於是回覆一個RST包給被動關閉方,被動關閉方就會收到一個錯誤(我們見的比較多的:connect reset by peer,這裡順便說下 Broken pipe,在收到RST包的時候,還往這個連接寫數據,就會收到 Broken pipe錯誤了),原本應該正常關閉的連接,給我來個錯誤,很難讓人接受;

2)防止已經斷開的連接1中在鏈路中殘留的FIN包終止掉新的連接2(重用了連接1的所有的5元素(源IP,目的IP,TCP,源端口,目的端口)),這個概率比較低,因為涉及到一個匹配問題,遲到的FIN分段的序列號必須落在連接2的一方的期望序列號範圍之內,雖然概率低,但是確實可能發生,因為初始序列號都是隨機產生的,並且這個序列號是32位的,會迴繞;

3)防止鏈路上已經關閉的連接的殘餘數據包(a lost duplicate packet or a wandering duplicate packet) 干擾正常的數據包,造成數據流的不正常。這個問題和2)類似。

3TIME_WAIT會帶來哪些問題呢?

TIME_WAIT帶來的問題注意是源於:一個連接進入TIME_WAIT狀態後需要等待2*MSL(一般是1到4分鐘)那麼長的時間才能斷開連接釋放連接佔用的資源,會造成以下問題:

1) 作為服務器,短時間內關閉了大量的Client連接,就會造成服務器上出現大量的TIME_WAIT連接,佔據大量的tuple,嚴重消耗著服務器的資源;

2) 作為客戶端,短時間內大量的短連接,會大量消耗的Client機器的端口,畢竟端口只有65535個,端口被耗盡了,後續就無法在發起新的連接了。

( 由於上面兩個問題,作為客戶端需要連本機的一個服務的時候,首選UNIX域套接字而不是TCP )。

TIME_WAIT很令人頭疼,很多問題是由TIME_WAIT造成的,但是TIME_WAIT又不是多餘的不能簡單將TIME_WAIT去掉,那麼怎麼來解決或緩解TIME_WAIT問題呢?可以進行TIME_WAIT的快速回收和重用來緩解TIME_WAIT的問題。有沒一些清掉TIME_WAIT的技巧呢?

我們將在下篇文章中繼續深入討論,敬請關注!


喜歡我的文章的話,就關注我吧!不要只收藏和轉發哦,每天至少兩篇編程知識給大家,都是本人多年的經驗總結!


分享到:


相關文章: