TCP為什么需要三次握手而不是兩次?


面試的時候遇到一個問題:TCP為什么需要三次握手而不是兩次?

網上對此問題的回答不盡相同,主要有兩種聲音:

1. 因為TCP需要確認通信雙方的序列號,所以,A要對B的序列號確認;

2. 防止已經失效的連接請求報文段突然又傳到服務端,因而產生錯誤。

第一條的討論可以參見 StackExchange

第二條主要來自於謝希仁老師的《計算機網絡》,第7版在P239。
書中舉了一個例子:A發出的第一個連接請求報文段沒有丟失,而是在網絡中滯留,以致延遲到連接釋放以后的某個時間才到達B,B接收到這個失效的報文段之后,就認為是新的連接請求,於是接受連接請求,分配資源,但是后續A並沒有數據發送過來,這樣B的資源就白白浪費了。於是,三次握手可以避免這種情況。

面試的時候,我答的就是第二條,面試官反駁說,服務器都會有超時機制,資源的浪費還會被回收,這個不是主要原因。

那什么是主要原因呢?下面說一下我的分析(最后補充面試官的答案)。

首先我依然認為第二條的說法是正確的,因為第二條就是來自 RFC793,原話是這樣的:

The principle reason for the three-way handshake is to prevent old duplicate connection initiations from causing confusion.

翻譯過來就是第二條:防止失效的重復的連接請求造成困擾。

但是,RFC中所表述的重點在:通過三次握手,通信雙方能夠正確交換序列號並正常通信,而不是造成資源浪費。(有點第一條的味道)。

RFC中舉了下面的例子來說明該情況,這也是區別於第一條的本質所在。


      TCP A                                                TCP B

  1.  CLOSED                                               LISTEN

  2.  SYN-SENT    --> <SEQ=100><CTL=SYN>               ...

  3.  (duplicate) ... <SEQ=90><CTL=SYN>               --> SYN-RECEIVED

  4.  SYN-SENT    <-- <SEQ=300><ACK=91><CTL=SYN,ACK>  <-- SYN-RECEIVED

  5.  SYN-SENT    --> <SEQ=91><CTL=RST>               --> LISTEN


  6.              ... <SEQ=100><CTL=SYN>               --> SYN-RECEIVED

  7.  SYN-SENT    <-- <SEQ=400><ACK=101><CTL=SYN,ACK>  <-- SYN-RECEIVED

  8.  ESTABLISHED --> <SEQ=101><ACK=401><CTL=ACK>      --> ESTABLISHED

                    Recovery from Old Duplicate SYN
  

在第3行,B接收到了A已經失效的序列號為90的報文段,認為是新的連接請求,於是狀態由LISTEN變成了SYN-RECEIVED;

在第4行,A接收到了B對於失效的連接請求的確認,但是注意,在A這邊,91這個序列號已經失效了,使用91是無法與B進行通信的,而B的狀態在第3行中不是LISTEN了,怎么再次建立連接呢?

在第5行A向B發送了控制位RST(reset)為1的報文段,將連接狀態重置,所以B的狀態回到了LISTEN;

接着在第6行B接收到序列號為100的連接請求,於是接下來就可以正常進行三次握手。

可以看到,第三次握手不一定會發送正確的ACK報文段,而是有可能重置B的連接狀態的。假如沒有第三次握手,在有失效連接報文段的情況下,A認為B的確認無效,無法使用91序列號,B卻已經建立連接,通信就無法進行下去,所以必須要有第三次握手。

PS:面試官的解釋:

A向B第一次發送的報文段可能在網絡中滯留,而后A可能發送了一個序列號也一樣的報文段,但是第一個報文段先到達B,於是建立連接並對A確認,A也認為連接建立了,但是后續通信的內容可能不是第一個TCP請求計划的那樣,雙方在數據格式以及加密解密上肯能存在不一致的情況,通信會發生錯誤。

當時聽的時候就感覺有問題(不過當時被唬住了),后來想一想,他的說法完全沒有道理,相同的連接請求,完全無法區分,就可以認為是同一個,之后的數據通信是按照最新的連接來的,一定不會產生通信的錯誤。


免責聲明!

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



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