天天看點

通俗易懂地講解TCP建立連接配接的三次握手和釋放連接配接的四次揮手

通過打電話的例子講解TCP的三次握手和四次揮手,通俗易懂,容易了解

TCP建立連接配接時,為什麼要進行三次揮手?

  每一次TCP連接配接都需要三個階段:連接配接建立、資料傳送和連接配接釋放。三次握手就發生在連接配接建立階段。 在謝希仁著《計算機網絡》第四版中講三次握手的目的是為了防止已失效的連接配接請求封包段突然又傳送到了服務端,因而産生錯誤。在另一部經典的《計算機網絡》一書中講三次握手的目的是為了解決網絡中存在延遲的重複分組的問題。   這兩種不用的表述其實闡明的是同一個問題。

  謝希仁版《計算機網絡》中的例子是這樣的,已失效的連接配接請求封包段的産生在這樣一種情況下:client發出的第一個連接配接請求封包段并沒有丢失,而是在某個網絡結點長時間的滞留了,以緻延誤到連接配接釋放以後的某個時間才到達server。本來這是一個早已失效的封包段。但server收到此失效的連接配接請求封包段後,就誤認為是client再次發出的一個新的連接配接請求。于是就向client發出确認封包段,同意建立連接配接。假設不采用三次握手,那麼隻要server發出确認,新的連接配接就建立了。由于現在client并沒有發出建立連接配接的請求,是以不會理睬server的确認,也不會向server發送資料。但server卻以為新的運輸連接配接已經建立,并一直等待client發來資料。這樣,server的很多資源就白白浪費掉了。采用三次握手的辦法可以防止上述現象發生。例如剛才那種情況,client不會向server的确認發出确認。server由于收不到确認,就知道client并沒有要求建立連接配接。   

  這個例子很清晰的闡釋了三次握手對于建立可靠連接配接的意義。在Google Groups的TopLanguage中看到一帖讨論TCP三向交握覺得很有意思。貼主提出的問題,在衆多回複中,有一條回複寫道:這個問題的本質是, 信道不可靠, 但是通信雙發需要就某個問題達成一緻. 而要解決這個問題, 無論你在消息中包含什麼資訊, 三次通信是理論上的最小值. 是以三次握手不是TCP本身的要求, 而是為了滿足"在不可靠信道上可靠地傳輸資訊"這一需求所導緻的. 請注意這裡的本質需求,信道不可靠, 資料傳輸要可靠. 三次達到了, 那後面你想接着握手也好, 發資料也好, 跟進行可靠資訊傳輸的需求就沒關系了. 是以,如果信道是可靠的, 即無論什麼時候發出消息, 對方一定能收到, 或者你不關心是否要保證對方收到你的消息, 那就能像UDP那樣直接發送消息就可以了. 。這可視為對三次握手目的的另一種解答思路。

舉個打電話的例子:

  A : 你好我是A,你聽得到我在說話嗎

  B : 聽到了,我是B,你聽到我在說話嗎

  A : 嗯,聽到了

  建立連接配接,開始聊天!

通俗易懂地講解TCP建立連接配接的三次握手和釋放連接配接的四次揮手
通俗易懂地講解TCP建立連接配接的三次握手和釋放連接配接的四次揮手

為什麼TCP協定終止連結要四次?

1、當主機A确認發送完資料且知道B已經接受完了,想要關閉發送資料口(當然确認信号還是可以發),就會發FIN給主機B。

2、主機B收到A發送的FIN,表示收到了,就會發送ACK回複。

3、但這是B可能還在發送資料,沒有想要關閉資料口的意思,是以FIN與ACK不是同時發送的,而是等到B資料發送完了,才會發送FIN給主機A。

4、A收到B發來的FIN,知道B的資料也發送完了,回複ACK, A等待2MSL以後,沒有收到B傳來的任何消息,知道B已經收到自己的ACK了,A就關閉連結,B也關閉連結了。

A為什麼等待2MSL,從TIME_WAIT到CLOSE?

 在Client發送出最後的ACK回複,但該ACK可能丢失。Server如果沒有收到ACK,将不斷重複發送FIN片段。是以Client不能立即關閉,它必須确認Server接收到了該ACK。Client會在發送出ACK之後進入到TIME_WAIT狀态。Client會設定一個計時器,等待2MSL的時間。如果在該時間内再次收到FIN,那麼Client會重發ACK并再次等待2MSL。所謂的2MSL是兩倍的MSL(Maximum Segment Lifetime)。MSL指一個片段在網絡中最大的存活時間,2MSL就是一個發送和一個回複所需的最大時間。如果直到2MSL,Client都沒有再次收到FIN,那麼Client推斷ACK已經被成功接收,則結束TCP連接配接。

這個網上轉載的例子不錯:

三次握手:

A:“喂,你聽得到嗎?”A->SYN_SEND

B:“我聽得到呀,你聽得到我嗎?”應答與請求同時發出 B->SYN_RCVD | A->ESTABLISHED

A:“我能聽到你,今天balabala……”B->ESTABLISHED

四次揮手:

A:“喂,我不說了。”A->FIN_WAIT1

B:“我知道了。等下,上一句還沒說完。Balabala…..”B->CLOSE_WAIT | A->FIN_WAIT2

B:”好了,說完了,我也不說了。”B->LAST_ACK

A:”我知道了。”A->TIME_WAIT | B->CLOSED

A等待2MSL,保證B收到了消息,否則重說一次”我知道了”,A->CLOSED

連結:https://zhuanlan.zhihu.com/p/21940234