三握四揮原因
首先,我們要知道TCP是全雙工的,即客戶端在給伺服器端傳送資訊的同時,伺服器端也可以給客戶端傳送資訊。而半雙工的意思是A可以給B發,B也可以給A發,但是A在給B發的時候,B不能給A發,即不同時,為半雙工。 單工為只能A給B發,B不能給A發; 或者是隻能B給A發,不能A給B發。
我們假設A和B是通訊的雙方。我理解的握手實際上就是通訊,發一次資訊就是進行一次握手。
- 第一次握手: A給B打電話說,你可以聽到我說話嗎?
- 第二次握手: B收到了A的資訊,然後對A說: 我可以聽得到你說話啊,你能聽得到我說話嗎?
- 第三次握手: A收到了B的資訊,然後說可以的,我要給你發信息啦!
在三次握手之後,A和B都能確定這麼一件事: 我說的話,你能聽到; 你說的話,我也能聽到。 這樣,就可以開始正常通訊了。
注意: HTTP是基於TCP協議的,所以每次都是客戶端傳送請求,伺服器應答,但是TCP還可以給其他應用層提供服務,即可能A、B在建立連結之後,誰都可能先開始通訊。
如果兩次,那麼B無法確定B的資訊A是否能收到,所以如果B先說話,可能後面的A都收不到,會出現問題 。
如果四次,那麼就造成了浪費,因為在三次結束之後,就已經可以保證A可以給B發信息,A可以收到B的資訊; B可以給A發信息,B可以收到A的資訊。
三次握手圖示

image.png
首先由Client發出請求連線即 SYN=1 ACK=0 (請看頭欄位的介紹), TCP規定SYN=1時不能攜帶資料,但要消耗一個序號,因此宣告自己的序號是 seq=x
然後 Server 進行回覆確認,即 SYN=1 ACK=1 seq=y, ack=x+1, 再然後 Client 再進行一次確認,但不用SYN 了,這時即為 ACK=1, seq=x+1, ack=y+1.
然後連線建立,為什麼要進行三次握手呢(兩次確認)。
- 建立三次握手主要是因為A傳送了再一次的確認,那麼A為什麼會再確認一次呢,主要是為了防止已失效的連線請求報文段又突然傳送給B,從而產生了錯誤。
- 所謂“已失效的連線請求報文”是這樣產生的,正常情況下,A發出連線請求,但是因為連線報文請求丟失而未收到確認,於是A再重傳一次連線請求,後來收到了請求,並收到了確認,建立了連線,資料傳輸完畢後,就釋放連結,A共傳送了兩次連線請求報文段,其中第一個丟失,第二個到達了B,沒有“已失效的連線請求報文段”,但是還有異常情況下,A傳送的請求報文連線段並沒有丟失,而是在某個網路節點滯留較長時間,以致延誤到請求釋放後的某個時間到達B,本來是一個早已失效的報文段,但是B收到了此失效連線請求報文段後,就誤以為A又重新發送的連線請求報文段,併發送確認報文段給A,同意建立連線,如果沒有三次握手,那麼B傳送確認後,連線就建立了,而此時A沒有傳送建立連線的請求報文段,於是不理會B的確認,也不會給B傳送資料,而B卻一直等待A傳送資料,因此B的許多資源就浪費了,採用三次握手的方式就可以防止這種事情發生,例如剛剛,A不理會B,就不會給B傳送確認,B收不到A的確認,就知道A不要求建立連線,就不會白白浪費資源
四次揮手圖示

image.png
四次揮手:
-
A:“喂,我不說了 (FIN)。”A->FIN_WAIT1
-
B:“我知道了(ACK)。等下,上一句還沒說完。Balabala…..(傳輸資料)”B->CLOSE_WAIT | A->FIN_WAIT2
-
B:”好了,說完了,我也不說了(FIN)。”B->LAST_ACK
-
A:”我知道了(ACK)。”A->TIME_WAIT | B->CLOSED
-
A等待2MSL,保證B收到了訊息,否則重說一次”我知道了”,A->CLOSED
這樣,通過四次揮手,可以把該說的話都說完,並且A和B都知道自己沒話說了,對方也沒花說了,然後就掛掉電話(斷開連結)了 。
當客戶A 沒有東西要傳送時就要釋放 A 這邊的連線,A會發送一個報文(沒有資料),其中 FIN 設定為1, 伺服器B收到後會給應用程式一個信,這時A那邊的連線已經關閉,即A不再發送資訊(但仍可接收資訊)。 A收到B的確認後進入等待狀態,等待B請求釋放連線, B資料傳送完成後就向A請求連線釋放,也是用FIN=1 表示, 並且用 ack = u+1(如圖), A收到後回覆一個確認資訊,並進入 TIME_WAIT 狀態, 等待 2MSL 時間。
為什麼要等待呢?
-
為了這種情況: B向A傳送 FIN = 1 的釋放連線請求,但這個報文丟失了, A沒有接到不會發送確認資訊, B 超時會重傳,這時A在 WAIT_TIME 還能夠接收到這個請求,這時再回復一個確認就行了。(A收到 FIN = 1 的請求後 WAIT_TIME會重新記時)
-
另外伺服器B存在一個保活狀態,即如果A突然故障宕機了,那B那邊的連線資源什麼時候能釋放呢? 就是保活時間到了後,B會發送探測資訊, 以決定是否釋放連線
為什麼連線的時候是三次握手,關閉的時候卻是四次握手?
- 答:因為當Server端收到Client端的SYN連線請求報文後,可以直接傳送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連線時,當Server端收到FIN報文時,很可能並不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端所有的報文都發送完了,我才能傳送FIN報文,因此不能一起傳送。故需要四步握手。