上文連接:html
對於"三次握手"咱們耳熟能詳,由於其相對的簡單。可是,咱們卻不常聽見「四次揮手」,就算聽過也未必能詳細地說明白它的具體過程。下面就爲你們詳盡,直觀,完整地介紹「四次揮手」的過程。服務器
所謂的四次揮手即TCP鏈接的釋放(解除)。鏈接的釋放必須是一方主動釋放,另外一方被動釋放。如下爲客戶端主動發起釋放鏈接的圖解:網絡
揮手以前主動釋放鏈接的客戶端結束ESTABLISHED階段。隨後開始「四次揮手」:tcp
(1)首先客戶端想要釋放鏈接,向服務器端發送一段TCP報文,其中:.net
標記位爲FIN,表示「請求釋放鏈接「;計算機網絡
序號爲Seq=U;3d
隨後客戶端進入FIN-WAIT-1階段,即半關閉階段。而且中止在客戶端到服務器端方向上發送數據,可是客戶端仍然能接收從服務器端傳輸過來的數據。htm
注意:這裏不發送的是正常鏈接時傳輸的數據(非確認報文),而不是一切數據,因此客戶端仍然能發送ACK確認報文。blog
(2)服務器端接收到從客戶端發出的TCP報文以後,確認了客戶端想要釋放鏈接,隨後服務器端結束ESTABLISHED階段,進入CLOSE-WAIT階段(半關閉狀態)並返回一段TCP報文,其中:
標記位爲ACK,表示「接收到客戶端發送的釋放鏈接的請求」;
序號爲Seq=V;
確認號爲Ack=U+1,表示是在收到客戶端報文的基礎上,將其序號Seq值加1做爲本段報文確認號Ack的值;
隨後服務器端開始準備釋放服務器端到客戶端方向上的鏈接。
客戶端收到從服務器端發出的TCP報文以後,確認了服務器收到了客戶端發出的釋放鏈接請求,隨後客戶端結束FIN-WAIT-1階段,進入FIN-WAIT-2階段
(3)服務器端自從發出ACK確認報文以後,通過CLOSED-WAIT階段,作好了釋放服務器端到客戶端方向上的鏈接準備,再次向客戶端發出一段TCP報文,其中:
標記位爲FIN,ACK,表示「已經準備好釋放鏈接了」。注意:這裏的ACK並非確認收到服務器端報文的確認報文。
序號爲Seq=W;
確認號爲Ack=U+1;表示是在收到客戶端報文的基礎上,將其序號Seq值加1做爲本段報文確認號Ack的值。
隨後服務器端結束CLOSE-WAIT階段,進入LAST-ACK階段。而且中止在服務器端到客戶端的方向上發送數據,可是服務器端仍然可以接收從客戶端傳輸過來的數據。
(4)客戶端收到從服務器端發出的TCP報文,確認了服務器端已作好釋放鏈接的準備,結束FIN-WAIT-2階段,進入TIME-WAIT階段,並向服務器端發送一段報文,其中:
標記位爲ACK,表示「接收到服務器準備好釋放鏈接的信號」。
序號爲Seq=U+1;表示是在收到了服務器端報文的基礎上,將其確認號Ack值做爲本段報文序號的值。
確認號爲Ack=W+1;表示是在收到了服務器端報文的基礎上,將其序號Seq值做爲本段報文確認號的值。
隨後客戶端開始在TIME-WAIT階段等待2MSL
爲何要客戶端要等待2MSL呢?見後文。
服務器端收到從客戶端發出的TCP報文以後結束LAST-ACK階段,進入CLOSED階段。由此正式確認關閉服務器端到客戶端方向上的鏈接。
客戶端等待完2MSL以後,結束TIME-WAIT階段,進入CLOSED階段,由此完成「四次揮手」。
與「三次揮手」同樣,在客戶端與服務器端傳輸的TCP報文中,雙方的確認號Ack和序號Seq的值,都是在彼此Ack和Seq值的基礎上進行計算的,這樣作保證了TCP報文傳輸的連貫性,一旦出現某一方發出的TCP報文丟失,便沒法繼續"揮手",以此確保了"四次揮手"的順利完成。
舉個栗子:把客戶端比做男孩,服務器比做女孩。經過他們的分手來講明「四次揮手」過程。
"第一次揮手":日久見人心,男孩發現女孩變成了本身討厭的樣子,忍無可忍,因而決定分手,隨即寫了一封信告訴女孩。
「第二次揮手」:女孩收到信以後,知道了男孩要和本身分手,怒火中燒,心中暗罵:你算什麼東西,當初你可不是這個樣子的!因而立馬給男孩寫了一封回信:分手就分手,給我點時間,我要把你的東西整理好,所有還給你!
男孩收到女孩的第一封信以後,明白了女孩知道本身要和她分手。隨後等待女孩把本身的東西收拾好。
「第三次揮手」:過了幾天,女孩把男孩送的東西都整理好了,因而再次寫信給男孩:你的東西我整理好了,快把它們拿走,今後你我恩斷義絕!
「第四次揮手」:男孩收到女孩第二封信以後,知道了女孩收拾好東西了,能夠正式分手了,因而再次寫信告訴女孩:我知道了,這就去拿回來!
這裏雙方都有各自的堅持。
- 女孩自發出第二封信開始,限定一天內收不到男孩回信,就會再發一封信催促男孩來取東西!
- 男孩自發出第二封信開始,限定兩天內沒有再次收到女孩的信就認爲,女孩收到了本身的第二封信;若兩天內再次收到女孩的來信,就認爲本身的第二封信女孩沒收到,須要再寫一封信,再等兩天.....
假若雙方信都能正常收到,最少只用四封信就能完全分手!這就是「四次揮手」。
TCP創建鏈接時之因此只須要"三次握手",是由於在第二次"握手"過程當中,服務器端發送給客戶端的TCP報文是以SYN與ACK做爲標誌位的。SYN是請求鏈接標誌,表示服務器端贊成創建鏈接;ACK是確認報文,表示告訴客戶端,服務器端收到了它的請求報文。
即SYN創建鏈接報文與ACK確認接收報文是在同一次"握手"當中傳輸的,因此"三次握手"很少也很多,正好讓雙方明確彼此信息互通。
TCP釋放鏈接時之因此須要「四次揮手」,是由於FIN釋放鏈接報文與ACK確認接收報文是分別由第二次和第三次"揮手"傳輸的。爲什麼創建鏈接時一塊兒傳輸,釋放鏈接時卻要分開傳輸?
- 創建鏈接時,被動方服務器端結束CLOSED階段進入「握手」階段並不須要任何準備,能夠直接返回SYN和ACK報文,開始創建鏈接。
- 釋放鏈接時,被動方服務器,忽然收到主動方客戶端釋放鏈接的請求時並不能當即釋放鏈接,由於還有必要的數據須要處理,因此服務器先返回ACK確認收到報文,通過CLOSE-WAIT階段準備好釋放鏈接以後,才能返回FIN釋放鏈接報文。
因此是「三次握手」,「四次揮手」。
爲的是確認服務器端是否收到客戶端發出的ACK確認報文
當客戶端發出最後的ACK確認報文時,並不能肯定服務器端可以收到該段報文。因此客戶端在發送完ACK確認報文以後,會設置一個時長爲2MSL的計時器。MSL指的是Maximum Segment Lifetime:一段TCP報文在傳輸過程當中的最大生命週期。2MSL便是服務器端發出爲FIN報文和客戶端發出的ACK確認報文所能保持有效的最大時長。
服務器端在1MSL內沒有收到客戶端發出的ACK確認報文,就會再次向客戶端發出FIN報文;
- 若是客戶端在2MSL內,再次收到了來自服務器端的FIN報文,說明服務器端因爲各類緣由沒有接收到客戶端發出的ACK確認報文。客戶端再次向服務器端發出ACK確認報文,計時器重置,從新開始2MSL的計時;
- 不然客戶端在2MSL內沒有再次收到來自服務器端的FIN報文,說明服務器端正常接收了ACK確認報文,客戶端能夠進入CLOSED階段,完成「四次揮手」。
因此,客戶端要經歷時長爲2SML的TIME-WAIT階段;這也是爲何客戶端比服務器端晚進入CLOSED階段的緣由
圖中顯示的就是完整的TCP鏈接釋放的」四次揮手」過程。在 80 -> 55389 中,假設80是本地(客戶端)端口,55389是服務器端口。80端口與55389之間的四次來回就是"四次揮手"過程。
注意:這裏與「第三次握手」的ACK並非表示確認的ACK報文。
」第二次揮手」服務器端返回的ACK確認報文以[ACK]做爲標誌位;其中報文序號Seq=558;確認號Ack=2246;
」第三次揮手」服務器端繼續返回的FIN贊成釋放鏈接報文以[FIN,ACK]做爲標誌位;其中報文序號Seq=558;確認號Ack=2246;
」第四次揮手」客戶端發出的ACK確認接收報文以[ACK]做爲標誌位;其中報文序號Seq=2446;確認號Ack=559;
後一次「揮手」傳輸報文中的序號Seq值等於前一次"握手"傳輸報文中的確認號Ack值;
後一次「揮手」傳輸報文中的確認號Ack值等於前一次"握手"傳輸報文中的序號Seq值;
故這是連續的「四次揮手」過程,與前面的分析相符。
參考資料: