tcp為什麼要三次握手,而不能二次握手?
謝希仁版《計算機網絡》中的例子是這樣的,“已失效的連接請求報文段”的產生在這樣一種情況下:client發出的第一個連接請求報文段並沒有丟失,而是在某個網絡結點長時間的滯留了,以致延誤到連接釋放以後的某個時間才到達server。本來這是一個早已失效的報文段。但server收到此失效的連接請求報文段後,就誤認為是client再次發出的一個新的連接請求。於是就向client發出確認報文段,同意建立連接。假設不采用“三次握手”,那麼隻要server發出確認,新的連接就建立了。由於現在client並沒有發出建立連接的請求,因此不會理睬server的確認,也不會向server發送ack包。(校注:此時因為client沒有發起建立連接請求,所以client處於CLOSED狀態,接受到任何包都會丟棄,謝希仁舉的例子就是這種場景。但是如果服務器發送對這個延誤的舊連接報文的確認的同時,客戶端調用connect函數發起了連接,就會使客戶端進入SYN_SEND狀態,當服務器那個對延誤舊連接報文的確認傳到客戶端時,因為客戶端已經處於SYN_SEND狀態,所以就會使客戶端進入ESTABLISHED狀態,此時服務器端反而丟棄了這個重複的通過connect函數發送的SYN包,見第三個圖。而連接建立之後,發送包由於SEQ是以被丟棄的SYN包的序號為準,而服務器接收序號是以那個延誤舊連接SYN報文序號為準,導致服務器丟棄後續發送的數據包)但server卻以為新的運輸連接已經建立,並一直等待client發來數據。這樣,server的很多資源就白白浪費掉了。采用“三次握手”的辦法可以防止上述現象發生。例如剛才那種情況,client不會向server的確認發出確認。server由於收不到確認,就知道client並沒有要求建立連接。
在謝希仁著《計算機網絡》第四版中講“三次握手”的目的是“為了防止已失效的連接請求報文段突然又傳送到了服務端,因而產生錯誤”。在另一部經典的《計算機網絡》(Andrew S.Tanenbaum著,第四版)一書中講“三次握手”的目的是為了解決“網絡中存在延遲的重複分組”的問題。這兩種不同的表述其實闡明的是同一個問題。
附華中科技大學有一題研究生入學考題,是下麵題目的中文翻譯版(不過我覺得這個答案有點牽強,畢竟現在tcp傳輸機製中都有定時器,會有超時重傳,不會導致死鎖的,當然如果沒有超時機製,死鎖還是可能的):
Imagine that a two-way handshake rather than a three-way handshake were used to set up connections. In other words, the third message was not required. Are deadlocks now possible? Give an example or show that none exist.
Answer:
Deadlocks are possible. For example, a packet arrives at A out of the blue, and A acknowledges it. The acknowledgement gets lost, but A is now open while B knows nothing at all about what has happened. Now the same thing happens to B, and both are
open, but expecting different sequence numbers. Timeouts have to be introduced to avoid the deadlocks.
網上有一段流傳很廣的解釋:
為什麼不能用兩次握手進行連接?
我們知道,3次握手完成兩個重要的功能,既要雙方做好發送數據的準備工作(雙方都知道彼此已準備好),也要允許雙方就初始序列號進行協商,這個序列號在握手過程中被發送和確認。
現在把三次握手改成僅需要兩次握手,死鎖是可能發生的。作為例子,考慮計算機S和C之間的通信,假定C給S發送一個連接請求分組,S收到了這個分組,並發 送了確認應答分組。按照兩次握手的協定,S認為連接已經成功地建立了,可以開始發送數據分組。可是,C在S的應答分組在傳輸中被丟失的情況下,將不知道S 是否已準備好,不知道S建立什麼樣的序列號,C甚至懷疑S是否收到自己的連接請求分組。在這種情況下,C認為連接還未建立成功,將忽略S發來的任何數據分 組,隻等待連接確認應答分組。而S在發出的分組超時後,重複發送同樣的分組。這樣就形成了死鎖。
校評:這個解釋也值得商榷,這裏指說S超時重傳,難道C沒有收到S的ACK信號,不會重新發送SYN信號麼? 隻要重新發送SYN,S端自然也會發送確認應答分組,這樣就不會導致死鎖。
最後更新:2017-04-03 07:57:10
上一篇:
linux下如何查詢未知庫所依賴的包
下一篇:
淘寶數據庫OceanBase SQL編譯器部分 源碼閱讀--Schema模式
【12.2新特性】In-Memory列存儲的FastStart管理
護衛神鏡像係統如夢安裝SQL SERVER?
iframe中的各種跳轉方法
負載均衡SLB高可用的四個層次
hdu 1067 Gap
Java麵向對象基礎--this關鍵字的解析
2015火車票搶票,放票時間,幾點放票
WinForm中提示Circular base class dependency involving 'TestEncryption.Form' and 'TestEncryption.Form
springboot(六):如何優雅的使用mybatis
《Linux From Scratch》第二部分:準備構建 第五章:構建臨時文件係統- 5.19. Diffutils-3.3