TCP三次握手、四次握手過程,以及原因分析
阿新 • • 發佈:2019-01-30
首先,是需要明白一些欄位的含義,這樣三次握手、四次握手的流程圖就立馬可以很輕鬆地理解,並迅速手繪了。
(至於這兩個流程圖,網上鋪天蓋地都是,這裡就不貼出來了。)
SYN:該欄位被設定為1(即true),表示請求建立連線
FIN:該欄位被設定為1(即true),表示請求關閉連線
seq:該欄位為請求序列號,譬如為seq=x, 能夠標示一個請求包,在眾多包種區分其身份
ack:該欄位為確認欄位,譬如ack=x+1,表示已經收到對方發來的seq=x的請求包。
然後TCP是個可以雙向通訊的協議,
一次 “請求連線——確認”操作,可以確保一方做好了傳送準備,另一方做好了接收準備,因此可以建議一個單向的連線;
一次 “請求關閉——確認”操作,可以確保一方發完了資料希望關閉傳送,另一方收到請求關閉接收,最後關閉掉一個單向的連線。
其實,無論是建立連線的過程,還是關閉連線的過程,實際上都由兩個單向連線的 建立過程/關閉過程組成的,也就是在邏輯流程上都可以認為是兩個二次握手,即都需要四次。只不過,三次握手中,服務端確認客戶端連線的那個過程,即是第一次單向連線的確認,又是第二次單向連線的請求,它把兩次互動合併成了一次,因此就變成了三次握手。
(至於說三次握手單純是因為避免這種情況:客戶端過去已經發送的請求,再次到達服務端,導致再次建立連線,而客戶端對此無應答,因此導致服務端資源白白浪費。這應該不是根本原因,因為每個請求包都有seq序列號呀,序列號相同的請求包再次到達,在協議設計上,完全可以用seq判斷出是否是已經過時的請求包。)
一、建立TCP連線:三次握手協議
客戶端:我要對你講話,你能聽到嗎;
服務端:我能聽到;而且我也要對你講話,你能聽到嗎;
客戶端:我也能聽到。
…….
互相開始通話
……..
二:關閉TCP連線:四次握手協議
客戶端:我說完了,我要閉嘴了;
服務端:我收到請求,我要閉耳朵了;
(客戶端收到這個確認,於是安心地閉嘴了。)
…….
服務端還沒傾訴完自己的故事,於是繼續嘮嘮叨叨向客戶端說了半天,直到說完為止
…….
服務端:我說完了,我也要閉嘴了;
客戶端:我收到請求,我要閉耳朵了;(事實上,客戶端為了保證這個確認包成功送達,等待了兩個最大報文生命週期後,才閉上耳朵。)
(服務端收到這個確認,於是安心地閉嘴了。)
#.客戶端收到請求包後,為什麼要等待兩個最大報文生命週期後,才閉上耳朵呢?
為了以防萬一,因為最後一個發往服務端B的確認包有可能丟失。若丟失,服務端這裡過了響應超時時間timeOut,會再次往客戶端A傳送關閉連線請求,這時候客戶端得保證自己還沒閉上耳朵,還能接收請求才行。
服務端B再次傳送的請求包到達客戶端A時間,絕不會超過 最大報文生命週期。
這裡的問題是,到底上面服務端的是如何判斷超時的(我不是很清楚),假如是以自己傳送請求時刻開始計時,半天未應答,為超時,那麼:
從服務端B傳送請求包的時刻開始算,經過( TimeOut + 最大報文生命週期 )後,A必須還能接收資料包。
那麼A需要等待的時間是:( TimeOut + 最大報文生命週期 ) - (上一個關閉l請求包從B傳送到A的時長)。
網上這塊兒都講得很模糊,一般就是說到A需要等待( TimeOut + 最大報文生命週期 ) < 2 * 最大報文生命週期,所以等待2 * 最大報文生命週期可以確保萬無一失。
事實上,這裡關鍵需要搞清楚服務端的是如何判斷超時的,我不是很清楚。但是假如是以自己傳送請求的時刻開始計時,那麼TimeOut應該是一個往返的最大時間吧,你們確定一個“請求-應答”往返的最大時間小於最大報文生命週期。
當然,所有地方都是說要等待 2 * 最大生命週期,雖然沒具體搞明白,但是我也同樣相信。只是,網上的各種解釋,都解析的模模糊糊,而且好多地方從邏輯上都不能完全說通誒,對那些解釋,我沒法完全相信。