TCP四次分手中,主動關閉方最後為什麼要等待2MSL之後才關閉連接?

為什麼不是收到Fin,發送ACK之後立即就關閉連接呢?


和TCP三次同步握手不一樣的是,TCP關閉連接用四次握手來實現,即A---&>B Fin, B---&>A ACK, B---&>A Fin, A---&>B ACK,為什麼要這樣?


A---&>B Fin, B---&>A ACK ,A屬於主動關閉方,收到B的ACK後,A到B的方向連接關閉,即half shutown ,這時A不能再發送數據了。


這種狀態下B還是可以單向發送數據的,B的數據發送完畢,也做關閉動作了:

B---&>A Fin, A---&>B ACK

B收到ACK,關閉連接。但是A無法知道ACK是否已經到達B,於是開始等待?等待什麼呢?假如ACK沒有到達B,B會為FIN這個消息超時重傳 timeout retransmit ,那如果A等待時間足夠,又收到FIN消息,說明ACK沒有到達B,於是再發送ACK,直到在足夠的時間內沒有收到FIN,說明ACK成功到達。這個等待時間至少是:B的timeout + FIN的傳輸時間,為了保證可靠,採用更加保守的等待時間2MSL。

MSL,Maximum Segment Life,這是TCP 對TCP Segment 生存時間的限制。

TTL, Time To Live ,IP對IP Datagram 生存時間的限制,255 秒,所以 MSL一般 = TTL = 255秒

A發出ACK,等待ACK到達對方的超時時間 MSL,等待FIN的超時重傳,也是MSL,所以如果2MSL時間內沒有收到FIN,說明對方安全收到FIN。


TCP的三次握手(建立連接)和四次揮手(關閉連接)

原因有二:
一、保證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,這樣可以保證本次連接的所有數據都從網路中消失。

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


沒有仔細研究過這個,我胡說一個好了。說錯了請各位大神溫柔地指正…
一方面原因會不會是確保sequence number不會出問題…如果立刻結束並開始下一個connection,可能會有之前傳輸比較慢的packet剛剛到,而它的sequence number又正好在新的
sliding window裡面。這樣就會弄混了…


unp1 v3 37頁


卷一有解答,說一點減小因延遲高擁塞大對報文傳輸的影響


ack有可能丟失,若丟失需要重試


很簡單,因為最後一次關閉的ACK你永遠無法知道對方是否有收到,所以需要等待一個包在網路中存在的最大周期,如果超過這個周期ACK沒有發送到對方位置,發送端就會收到丟包命令(這個命令是由網路控制協議發出的),進而可以進行重發,反之則認為對方收到了ACK,結束wait。


推薦閱讀:

tcp首部只有埠號沒有ip地址,那麼網路層怎麼知道目的ip地址的呢?
關於CSMA/CD的問題?
SCTP同時具有TCP和UDP的優點,但是為什麼應用不廣?
如何正確關閉 tcp 連接?
同一網段內的兩台主機通信是否需要路由器?

TAG:計算機網路 | TCPIP | TCP |