接下來,以三個方面分析三次握手的原因:
1、三次握手才可以阻止重復歷史連接的初始化(主要原因)
2、三次握手才可以同步雙方的初始化序列號
3、三次握手才可以避免資源浪費
原因一:避免歷史連接
? ? ? ? 簡單來說,三次握手的首要原因是為了防止舊的重復連接初始化造成混亂。
? ? ? ? 我們考慮個場景,客戶端發送了SYN(seq=90)報文,然后客戶端宕機了,而且這個SYN報文還被網絡阻塞了,服務端并沒有收到,接著客戶端重啟后,又重新向服務端建立連接,發送了SYN(seq=100)報文。? ? ? ?
? ? ? ? 三次握手是如何阻止歷史連接的?
? ? ? ? ?客戶端連續發送多次SYN(都是同一個四元組)建立連接的報文,在網絡擁堵情況下:
- ? 一個舊SYN報文比最新的SYN報文早到達了服務端,那么此時服務端就會回一個SYN+ACK報文給客戶端,此報文中的確認號是91(90+1)。
- 客戶端收到后,發現自己期望收到的確認號是100+1,而不是90+1,于是就會回RST報文。
- 服務端收到RST報文后,就會釋放連接。
- 后續最新的SYN抵達了服務端后,客戶端與服務端就可以正常的完成三次握手了。
? ? ? ? 上述中的“舊SYN報文”稱為歷史連接,TCP使用三次握手建立連接的最主要原因就是防止歷史連接初始化了連接。
? ? ? ? 如果是兩次握手連接,就無法阻止歷史連接,那為什么TCP兩次握手無法阻止歷史連接呢?
? ? ? ? 因為在兩次握手的情況下,服務器沒有中間狀態給客戶端來阻止歷史連接,導致服務端可能建立一個歷史連接,造成資源浪費。
原因二:同步雙方初始序列號
? ? ? ? TCP協議的通信雙方,都必須維護一個序列號,序列號是可靠傳輸的一個關鍵因素,它的作用:
- ? 接收方可以去除重復的數據;
- 接收方可以根據數據包的序列號按序接收;
- 可以標識發送出去的數據包中,哪些是已經被對方收到的(通過ACK報文中的序列號知道);
? ? ? ? 可見,序列號在TCP連接中占據著非常重要的作用,所以當客戶端發送攜帶初始序列號的SYN報文的時候,需要服務端回一個ACK應答報文,表示客戶端的SYN報文已被服務端成功接收,那當服務端發送初始序列號給客戶端的時候,依然也要得到客戶端的應答回應,這樣一來一回,才能確保雙方的初始序列號能被可靠的同步。
? ? ? ? 四次握手其實也能夠可靠的同步雙方的初始化序號,但由于第二步和第三步可以優化成一步,所以就成了三次握手。
原因三:避免資源浪費
? ? ? ? 如果服務端發送的SYN報文在網絡中阻塞了,重復發送多次SYN報文,那么服務端在收到請求后就會建立多個冗余的無效連接,造成不必要的資源浪費。(缺少中間狀態--RST)
總結
? ? ? ? TCP建立連接時,通過三次握手能防止歷史連接的建立,能減少不必要的資源開銷,能幫助雙方同步初始化序列號。序列號能保證數據包不重復、不丟棄和按序傳輸。
? ? ? ? 不使用兩次握手和四次握手的原因?
- ? 兩次握手:無法防止歷史連接的建立,會造成雙方資源的浪費,也無法可靠的同步雙方序列號。
- 四次握手:三次握手就已經理論上最少可靠連接建立,所以不需要使用更多的通信次數。