TCP狀態(tài)轉(zhuǎn)移
在前一篇文章【面試必考】TCP協(xié)議“三次握手”與“四次揮手”已經(jīng)介紹了TCP
協(xié)議的三次握手和四次揮手??偟膩碚f,TCP通信過程包括三個步驟:建立TCP連接(三次握手)、數(shù)據(jù)傳輸、終止TCP連接(四次揮手)。但是在這個通信過程中,有非常復(fù)雜的狀態(tài)問題,下面就來了解一下進行TCP協(xié)議通信時候的狀態(tài)轉(zhuǎn)移。
TCP協(xié)議根據(jù)連接時接收到報文的不同類型,采取相應(yīng)動作也不同,還要處理各個狀態(tài)的關(guān)系,如當收到握手報文時候、超時的時候、用戶主動關(guān)閉的時候等都需要不一樣的狀態(tài)去采取不一樣的處理。在LwIP中,為了實現(xiàn)TCP
協(xié)議的狀態(tài)描述,定義了11種連接時候的狀態(tài):
1static const char *const tcp_state_str[] = {
2 "CLOSED", //關(guān)閉狀態(tài)(無連接)
3 "LISTEN", //監(jiān)聽狀態(tài)
4 "SYN_SENT", //已發(fā)起請求連接(等待確認)
5 "SYN_RCVD", //已收到請求連接
6 "ESTABLISHED",//穩(wěn)定連接狀態(tài)
7 "FIN_WAIT_1", //單向請求終止連接狀態(tài)
8 "FIN_WAIT_2", //對方已應(yīng)答請求終止連接
9 "CLOSE_WAIT", //等待終止連接
10 "CLOSING", //兩端同時關(guān)閉
11 "LAST_ACK", //服務(wù)器等待對方接受關(guān)閉
12 "TIME_WAIT" //關(guān)閉成功(2MSL等待狀態(tài))
13};
LISTEN
:表示監(jiān)聽狀態(tài)。服務(wù)器
調(diào)用了listen函數(shù)進入監(jiān)聽狀態(tài),客戶端可以開始進行連接了。SYN_SENT
:表示客戶端已經(jīng)發(fā)送了SYN
報文請求連接(同時在等待服務(wù)器的確認)。當客戶端調(diào)用connect
函數(shù)發(fā)起連接時,首先發(fā)SYN給服務(wù)端,然后自己進入SYN_SENT
狀態(tài),并等待服務(wù)端發(fā)送ACK+SYN
報文(握手應(yīng)答報文)進行確認。SYN_RCVD
:在每一個 TCP 連接建立時,都要進行三次握手,這個狀態(tài)表示服務(wù)器
接收到客戶端發(fā)來的同步報文段(第一次握手),并且向客戶端發(fā)送了確認同步報文段(第二次握手)之后的狀態(tài),在這個狀態(tài)時,其實連接已經(jīng)經(jīng)歷了兩次握手。ESTABLISHED
:這個狀態(tài)是處于穩(wěn)定連接狀態(tài),建立連接的TCP協(xié)議兩端的主機都是處于這個狀態(tài),它們相互知道彼此的窗口大小、序列號、最大報文段等信息。FIN_WAIT_1
與FIN_WAIT_2
:處于這個狀態(tài)一般都是客戶端主機
單向請求終止連接,然后主機等待服務(wù)器
的回應(yīng),而如果服務(wù)器產(chǎn)生應(yīng)答,則主機狀態(tài)轉(zhuǎn)移為FIN_WAIT_2
,此時<客戶端 -> 服務(wù)器
>方向上的TCP連接就斷開,但是<服務(wù)器 -> 客戶端
>方向上的連接還是存在的。此處有一個注意的地方:如果主機處于FIN_WAIT_2
狀態(tài),說明主機已經(jīng)發(fā)出了FIN
報文段,并且服務(wù)器也已對它進行確認,除非客戶端是在實行半關(guān)閉狀態(tài),否則將等待服務(wù)器主機的應(yīng)用層處理關(guān)閉連接,因為服務(wù)器已經(jīng)意識到它已收到FIN
報文段,它需要發(fā)一個 FIN 來關(guān)閉<服務(wù)器 -> 客戶端
>方向上的連接。這樣客戶端這端才會從FIN_WAIT_2
狀態(tài)進入TIME_WAIT
狀態(tài)。如果是網(wǎng)絡(luò)不好或者是服務(wù)器不發(fā)送FIN
報文段的時候,這意味著客戶端這端可能永遠保持這個FIN_WAIT_2
狀態(tài),從而無法 進入CLOSE_WAIT
狀態(tài),并一直占用這個端口連接或者socket
,在嵌入式中,如果存在多個這種狀態(tài)的話,則這很可能導(dǎo)致內(nèi)存耗盡。CLOSE_WAIT
:在收到客戶端
主動斷開連接的 FIN 報文段(第一次揮手)后,服務(wù)器
返回給客戶端確認報文段(第二次揮手)后的狀態(tài)。TIME_WAIT
狀態(tài):TIME_WAIT
狀態(tài)也稱為2MSL等待狀態(tài)
。
具體見下圖:
-
.
紅色
虛線:表示服務(wù)器的狀態(tài)轉(zhuǎn)移。 -
. 黑色實線:表示客戶端的狀態(tài)轉(zhuǎn)移。
TCP協(xié)議狀態(tài)轉(zhuǎn)移
RST報文
順便再提一點不太常見的TCP協(xié)議狀態(tài)轉(zhuǎn)移,主要是針對服務(wù)器端的(綠色那條):
- 服務(wù)器在收到
SYN
握手報文后,再收到了客戶端的RST
報文,那么它會重新進入監(jiān)聽狀態(tài),再重新等待連接。
一般說來,無論何時一個報文段發(fā)往基準的連接出現(xiàn)錯誤, TCP
都會發(fā)出一個復(fù)位報文段(這里提到的基準的連接
是指由目的 IP地址、目的端口號、源 IP地址和源端口號都是已知
的連接。
此外產(chǎn)生復(fù)位的另一種常見情況是當連接請求到達時,目的端口并沒有在監(jiān)聽中,當一個數(shù)據(jù)報到達目的端口時,它將產(chǎn)生一個ICMP
端口不可達的信息,同時TCP協(xié)議將進行復(fù)位,當然啦,在lwip中這些ICMP
端口不可達報文都會被丟棄的,也不用管那么多。
TIME_WAIT狀態(tài)
第一次看這個轉(zhuǎn)移圖的時候,可能很多人都有疑惑,為什么要有一個 TIME_WAIT
狀態(tài)?為什么不能直接到達 CLOSED
狀態(tài)?
每個具體TCP
連接的實現(xiàn)必須選擇一個TCP
報文段最大生存時間MSL
(Maximum Segment Lifetime),就如IP數(shù)據(jù)報
中的TTL
字段表示報文在網(wǎng)絡(luò)中生存的時間一樣。MSL
是任何報文段被丟棄前在網(wǎng)絡(luò)內(nèi)的最長時間,這個時間是有限的,為什么需要等待呢?我們知道 IP數(shù)據(jù)報 是不可靠的,而TCP報文段是封裝在IP數(shù)據(jù)報中,TCP協(xié)議必須保證發(fā)出的 ACK 報文段是正確被對方接收, 因此處于該狀態(tài)的主機必須在這個狀態(tài)停留最長時間為2倍的MSL,以防最后這個ACK丟失,因為TCP協(xié)議必須保證數(shù)據(jù)能準確送達目的地。
我們來假設(shè)一下 :假設(shè)沒有 TIME_WAIT
這種狀態(tài)?,F(xiàn)實中,網(wǎng)絡(luò)環(huán)境不是理想的。在數(shù)據(jù)包傳輸?shù)倪^程中,難免會有一些延時啊、丟包啊
的情況發(fā)生。如果在客戶端的最后一個確認報文段
發(fā)出去之后,由于某種原因,沒有到達服務(wù)端,服務(wù)端在超時后,就會向客戶端重新發(fā)一個 FIN 報文段,請求重傳這個已經(jīng)丟失的確認報文段
。但由于在客戶端,連接實際上已經(jīng)斷開,端口已經(jīng)關(guān)閉。那么在客戶端收到這個報文段后,會向服務(wù)端發(fā)送一個 RST
報文段請求重連(這也是為什么我要在前面講解RST
的原因 ),而此時服務(wù)器收到這個 RST
報文段后,會認為是錯誤的,因為在服務(wù)器看來都沒斷開連接,它所期望收到的是確認報文段。所以這個時候客戶端是不允許直接CLOSE
關(guān)閉了事的,因此它需要等待服務(wù)器確認了,再CLOSE
。
再假設(shè)一下:如果沒有 TIME_WAIT
這種狀態(tài),客戶端在關(guān)閉連接后,再次成功建立新的連接
,客戶端任然可能會收到服務(wù)器的最后一個確認報文段
,但是由于序號
不同(重新建立連接時的序號是隨機
的,這點很重要,要記住),客戶端會要求服務(wù)端重傳
數(shù)據(jù)包,這樣,連接就必然會混亂出錯。而在 TIME_WAIT
這種狀態(tài)等待一段時間是為了讓本次連接的時間內(nèi)所產(chǎn)生的所有報文都從網(wǎng)絡(luò)中消失,使得下一個新的連接不會出現(xiàn)舊的報文。
而 TIME_WAIT
狀態(tài)的等待時間一般是 2MAL
,并且客戶端連接的端口沒有釋放,這樣,讓前一個連接的報文段有足夠的時間被處理或者丟棄,也就不會出現(xiàn)這個問題。
這才是TCP協(xié)議優(yōu)雅且可靠
的終止連接方式啊!太強大了,我得膜拜一下~
-
狀態(tài)
+關(guān)注
關(guān)注
0文章
16瀏覽量
11947 -
LwIP
+關(guān)注
關(guān)注
2文章
86瀏覽量
27173 -
TCP協(xié)議
+關(guān)注
關(guān)注
1文章
91瀏覽量
12070
發(fā)布評論請先 登錄
相關(guān)推薦
評論