網(wǎng)絡知識(1) - TCP連接關(guān)閉四次揮手

歡迎訪問我的個人網(wǎng)站獲取更佳排版體驗: https://pengrl.com/p/49801

TCP連接關(guān)閉狀態(tài)遷移圖

本文包含內(nèi)容:

  • TCP FIN 簡介
  • TCP ACK 簡介
  • 為什么 TCP 連接關(guān)閉是四次揮手
  • 先看最常見的正常關(guān)閉流程
  • 什么時候進入 CLOSING 狀態(tài)
  • TIME_WAIT 狀態(tài)的作用
  • 為什么被動關(guān)閉端不需要維持一個類似 TIME_WAIT 的狀態(tài),萬一發(fā)出的 ACK 也丟失了呢
  • 最后,再奉上一張 geek 味十足的tcp狀態(tài)遷移圖

TCP FIN 簡介

FIN可以理解為TCP包中的一種信令類型。事實上,F(xiàn)IN是TCP包頭中的一個固定標志位,該標志位為1時,表示本端關(guān)閉連接。

TCP ACK 簡介

TCP基于IP協(xié)議,IP包不保證可靠傳輸。
TCP的做法是,發(fā)送端發(fā)送的每個TCP包攜帶序號信息,接收端通過序號處理亂序包和重復包。
并且,接收端持續(xù)向發(fā)送端發(fā)送ACK信息,反饋接收端接收到的流式數(shù)據(jù)的位置,從而使得發(fā)送端有能力檢測出對端未接收到數(shù)據(jù),發(fā)送端可重新發(fā)送丟失的數(shù)據(jù)。

為什么 TCP 連接關(guān)閉是四次揮手

由于TCP可雙向發(fā)送數(shù)據(jù),所以TCP連接關(guān)閉至少需要兩次揮手,即兩端各自發(fā)送FIN,表示本端已無數(shù)據(jù)需要發(fā)送。
又由于FIN包也有丟失的可能,所以出現(xiàn)了ACK of FIN,即對FIN包也回復ACK確認,以保證FIN包丟失后可以重傳。
事實上,由于FIN和ACK of FIN都有可能丟失,TCP連接關(guān)閉的設計比四次揮手通常被理解的情況要更復雜些。
我們接下來看。

先看最常見的正常關(guān)閉流程

提示,本文的后續(xù)內(nèi)容建議結(jié)合上面的TCP連接關(guān)閉狀態(tài)連接圖配套食用。

以下主動關(guān)閉端指未收到對端FIN的情況下本端發(fā)送FIN。被動關(guān)閉端則是先收到對端發(fā)送的FIN,之后某個時間點本端發(fā)送FIN。

主動關(guān)閉端
流程為: 發(fā)送FIN,接收ACK,接收FIN,發(fā)送ACK
狀態(tài)遷移為: ESTAB -> FINWAIT_1 -> FINWAIT_2 -> TIME_WAIT -> CLOSED

被動關(guān)閉端
流程為: 接收FIN,發(fā)送ACK,發(fā)送FIN,接收ACK
狀態(tài)遷移為: ESTAB -> CLOSE_WAIT -> LAST_ACK -> CLOSED

什么時候進入 CLOSING 狀態(tài)

有兩種情況:
第一種,由于ACK of FIN可能丟失,所以當被動關(guān)閉端發(fā)出的ACK丟失,而被動關(guān)閉端緊接著又發(fā)出了FIN,那么主動關(guān)閉端會先收到FIN,從而進入CLOSING狀態(tài)。
第二種,兩端都在還未收到FIN的的情況,發(fā)出了FIN,即兩端同時關(guān)閉,那么可能出現(xiàn)發(fā)出FIN后還沒收到對應的ACK,立馬就收到對端發(fā)出的FIN。第二種情況下,兩端都是主動關(guān)閉端,它們都是首先從ESTAB狀態(tài)進入FINWAIT_1狀態(tài),不再走CLOSE_WAIT那條狀態(tài)遷移路線。

TIME_WAIT 狀態(tài)的作用

簡單來說,由于ACK of FIN存在丟失的可能。主動關(guān)閉端被動關(guān)閉端回復的ACK of FIN可能丟失(此ACK為主動關(guān)閉端發(fā)出的最后一個包)。而TCP是不會再去對ACK做ACK確認的。
那么如果出現(xiàn)主動關(guān)閉端發(fā)出的ACK丟失了的情況,被動關(guān)閉端由于收不到ACK將停留在LAST_ACK狀態(tài),無法進入CLOSED狀態(tài)。
TCP協(xié)議處理這種異常情況的做法是:被動關(guān)閉端如果收不到ACK將觸發(fā)超時重新發(fā)送FIN;在主動關(guān)閉端維持一個TIME_WAIT,繼續(xù)接收FIN并作出ACK回復。

TIME_WAIT的維持時間是2個MSL,MSL是Maximum Segment Lifetime的縮寫,即報文最大生存時間。

其實講到這我們已經(jīng)可以知道,作為主動關(guān)閉端,進入TIME_WAIT狀態(tài)并維持一段時間是TCP協(xié)議本身的設計,并不是一種異常狀態(tài)。
之后我會再單獨針對TIME_WAIT寫一篇文章,描述TIME_WAIT的維持時間為什么是2個MSL,TIME_WAIT的一些內(nèi)核相關(guān)參數(shù)的設置,以及服務器上出現(xiàn)大量TIME_WAIT時我們應該怎么辦。

為什么被動關(guān)閉端不需要維持一個類似 TIME_WAIT 的狀態(tài),萬一發(fā)出的 ACK 也丟失了呢

我在學習TCP連接關(guān)閉時,有一個疑問,既然主動關(guān)閉端為了解決發(fā)送的ACK丟失,維持了一個TIME_WAIT狀態(tài)。
那么被動關(guān)閉端發(fā)出的ACK也可能丟失,如果這個ACK丟失(其他包都未丟失),被動關(guān)閉端會順利進入CLOSED狀態(tài),那么主動關(guān)閉端豈不是會一直停留在CLOSING狀態(tài)。

后來在網(wǎng)上詢問了一些高手,他們的解釋是并不會出現(xiàn)這種情況。
理解這個問題,首先要理解ACK of FIN可以是一個單獨的TCP包,也可以不是。
事實上,ACK信息也是TCP包頭中的一個固定字段。
所以,當被動關(guān)閉端關(guān)閉連接發(fā)送FIN時,F(xiàn)IN中的ACK字段也會攜帶對端發(fā)出FIN所對應的ACK信息。只要主動關(guān)閉端收到了這個FIN,也即可以確認對端已經(jīng)收到了本端發(fā)出的FIN。
這種情況下,可以理解為主動關(guān)閉端FINWAIT_1收到FIN后,進入CLOSING狀態(tài),之后迅速進入了TIME_WAIT狀態(tài)。

最后,奉上一張geek味十足的tcp狀態(tài)遷移圖

圖片來源: RFC 793 - Transmission Control Protocol (https://tools.ietf.org/html/rfc793)

另外從中可以看到,SYN_RCVD狀態(tài)也可以發(fā)送FIN從而進入FINWAIT_1。

                              +---------+ ---------\      active OPEN
                              |  CLOSED |            \    -----------
                              +---------+<---------\   \   create TCB
                                |     ^              \   \  snd SYN
                   passive OPEN |     |   CLOSE        \   \
                   ------------ |     | ----------       \   \
                    create TCB  |     | delete TCB         \   \
                                V     |                      \   \
                              +---------+            CLOSE    |    \
                              |  LISTEN |          ---------- |     |
                              +---------+          delete TCB |     |
                   rcv SYN      |     |     SEND              |     |
                  -----------   |     |    -------            |     V
 +---------+      snd SYN,ACK  /       \   snd SYN          +---------+
 |         |<-----------------           ------------------>|         |
 |   SYN   |                    rcv SYN                     |   SYN   |
 |   RCVD  |<-----------------------------------------------|   SENT  |
 |         |                    snd ACK                     |         |
 |         |------------------           -------------------|         |
 +---------+   rcv ACK of SYN  \       /  rcv SYN,ACK       +---------+
   |           --------------   |     |   -----------
   |                  x         |     |     snd ACK
   |                            V     V
   |  CLOSE                   +---------+
   | -------                  |  ESTAB  |
   | snd FIN                  +---------+
   |                   CLOSE    |     |    rcv FIN
   V                  -------   |     |    -------
 +---------+          snd FIN  /       \   snd ACK          +---------+
 |  FIN    |<-----------------           ------------------>|  CLOSE  |
 | WAIT-1  |------------------                              |   WAIT  |
 +---------+          rcv FIN  \                            +---------+
   | rcv ACK of FIN   -------   |                            CLOSE  |
   | --------------   snd ACK   |                           ------- |
   V        x                   V                           snd FIN V
 +---------+                  +---------+                   +---------+
 |FINWAIT-2|                  | CLOSING |                   | LAST-ACK|
 +---------+                  +---------+                   +---------+
   |                rcv ACK of FIN |                 rcv ACK of FIN |
   |  rcv FIN       -------------- |    Timeout=2MSL -------------- |
   |  -------              x       V    ------------        x       V
    \ snd ACK                 +---------+delete TCB         +---------+
     ------------------------>|TIME WAIT|------------------>| CLOSED  |
                              +---------+                   +---------+
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容