TCP連線狀態詳解

2022-10-09 03:51:10 字數 3538 閱讀 8361

對於linux 套接字通訊,從連線建立到連線斷開,其狀態總共有11種,在三次握手和四次揮手,狀態變化比較快,在連線建立時,狀態比較穩定,下面簡單介紹一下各個狀態的情況。

狀態彙總(11種):

listen:偵聽來自遠方的tcp埠的連線請求

syn-sent:再傳送連線請求後等待匹配的連線請求(客戶端)

syn-received:再收到和傳送乙個連線請求後等待對方對連線請求的確認(伺服器)

established:代表乙個開啟的連線

fin-wait-1:等待遠端tcp連線中斷請求,或先前的連線中斷請求的確認

fin-wait-2:從遠端tcp等待連線中斷請求

close-wait:等待從本地使用者發來的連線中斷請求

closing:等待遠端tcp對連線中斷的確認

last-ack:等待原來的發向遠端tcp的連線中斷請求的確認

time-wait:等待足夠的時間以確保遠端tcp接收到連線中斷請求的確認

closed:沒有任何連線狀態

tcp 3次握手:

過程分析:

第1次握手:客戶端的應用程序主動開啟,並向服務端發出請求報文段。其首部中:syn=1,seq=x。

第2次握手:伺服器應用程序被動開啟。若同意客戶端的請求,則發回確認報文,其首部中:syn=1,ack=1,ack=x+1,seq=y。

第3次握手:客戶端收到確認報文之後,通知上層應用程序連線已建立,並向伺服器發出確認報文,其首部:ack=1,ack=y+1。當伺服器收到客戶端的確認報文之後,也通知其上層應用程序連線已建立。

建立連線時的狀態變遷:

一開始,建立連線之前伺服器和客戶端的狀態都為closed。伺服器建立socket後開始監聽,變為listen狀態。客戶端請求建立連線,向伺服器傳送syn報文,客戶端的狀態變為syn_sent。伺服器收到客戶端的報文後向客戶端傳送ack和syn報文,此時伺服器的狀態變為syn_rcvd。然後,客戶端收到ack、syn,就向伺服器傳送ack,客戶端狀態變為established,伺服器收到客戶端的ack後也變為established。此時,3次握手完成,連線建立!

tcp 4次揮手:

(1) tcp客戶端傳送乙個fin,用來關閉客戶到伺服器的資料傳送。

(2) 伺服器收到這個fin,它發回乙個ack,確認序號為收到的序號加1。和syn一樣,乙個fin將占用乙個序號。

(3) 伺服器關閉客戶端的連線,傳送乙個fin給客戶端。

(4) 客戶端發回ack報文確認,並將確認序號設定為收到序號加1。

斷開連線時的狀態變遷

由於tcp連線是全雙工的,斷開連線會比建立連線麻煩一點點。客戶端先向伺服器傳送fin報文,請求斷開連線,其狀態變為fin_wait1。伺服器收到fin後向客戶端發生ack,伺服器狀態變為close_wait。客戶端收到ack後就進入fin_wait2狀態。此時連線已經斷開了一半了。如果伺服器還有資料要傳送給客戶端,就會繼續傳送。直到發完了,就傳送fin報文,此時伺服器進入last_ack狀態。客戶端收到伺服器的fin後,馬上傳送ack給伺服器,此時客戶端進入time_wait狀態,再過了2msl長的時間後進入closed狀態。伺服器收到客戶端的ack就進入closed狀態。

至此,還有乙個狀態沒有提及:closing狀態。closing狀態表示客戶端發生了fin,但沒有收到伺服器的ack,卻收到了伺服器的fin。這種情況發生在伺服器傳送的ack丟包的時候,因為網路傳輸有時會有意外。

下面介紹一下各個狀態:

closed:

表示初始狀態。

listen:

伺服器端的某個socket處於監聽狀態

syn_rcvd:

這個狀態表示接受到了syn報文,在正常情況下,這個狀態是伺服器端的socket在建立tcp連線時的三次握手會話過程中的乙個中間狀態,很短暫,基本上用netstat是很難看到這種狀態的,因此這種狀態時,當收到客戶端的ack報文後,它會進入到established狀態。

syn_sent:

這個狀態與syn_rcvd遙想呼應,當客戶端socket執行connect連線時,它首先傳送syn報文,因此也隨即它會進入到了syn_sent狀態,並等待服務端的傳送三次握手中的第2個報文。syn_sent狀態表示客戶端已傳送syn報文。

established:

表示連線已經建立了。

fin_wait_1:

這個狀態要好好解釋一下,其實fin_wait_1和fin_wait_2狀態的真正含義都是表示等待對方的fin報文。而這兩種狀態的區別是:fin_wait_1狀態實際上是當socket在established狀態時,它想主動關閉連線,向對方傳送了fin報文,此時該socket即進入到fin_wait_1狀態。而當對方回應ack報文後,則進入到fin_wait_2狀態,當然在實際的正常情況下,無論對方何種情況下,都應該馬上回應ack報文,所以fin_wait_1狀態一般是比較難見到的,而fin_wait_2狀態還有時常常可以用netstat看到。

fin_wait_2:

上面已經詳細解釋了這種狀態,實際上fin_wait_2狀態下的socket,表示半連線,也即有一方要求close連線,但另外還告訴對方,我暫時還有點資料需要傳送給你,稍後再關閉連線這就是著名的半關閉的狀態了,這是在關閉連線時,客戶端和伺服器兩次握手之後的狀態。在這個狀態下,應用程式還有接受資料的能力,但是已經無法傳送資料,但是也有一種可能是,客戶端一直處於fin_wait_2狀態,而伺服器則一直處於wait_close狀態,而直到應用層來決定關閉這個狀態

time_wait:

表示收到了對方的fin報文,並傳送出了ack報文,就等2msl後即可回到closed可用狀態了。如果fin_wait_1狀態下,收到了對方同時帶fin標誌和ack標誌的報文時,可以直接進入到time_wait狀態,而無須經過fin_wait_2狀態。

closing:

這裡先說一下另一種狀態(同時開啟),rst是另一種關閉連線的方式,應用程式應該可以判斷rst包的真實性,即是否為異常中止。而同時開啟和同時關閉則是兩種特殊的tcp狀態,發生的概率很小。

下面說closing狀態

這種狀態比較特殊,實際情況中應該是很少見,屬於一種比較罕見的例外狀態。正常情況下,當你傳送fin報文後,按理來說是應該先收到(或同時收到)對方的ack報文,再收到對方的fin報文。但是closing狀態表示你傳送fin報文後,並沒有收到對方的ack報文,反而卻也收到了對方的fin報文。什麼情況下會出現此種情況呢?其實細想一下,也不難得出結論:那就是如果雙方幾乎在同時close乙個socket的話,那麼就出現了雙方同時傳送fin報文的情況,也就會出現closing狀態,表示雙方都正在關閉socket連線。

close_wait:

這種狀態的含義其實是表示在等待關閉。怎麼理解呢?當對方close乙個socket後傳送fin報文給自己,你系統毫無疑問地會回應乙個ack報文給對方,此時則進入到close_wait狀態。接下來呢,實際上你真正需要考慮的事情是檢視你是否還有資料傳送給對方,如果沒有的話,那麼你也就可以close這個socket,傳送fin報文給對方,也即關閉連線。所以你在close_wait狀態下,需要完成的事情是等待你去關閉連線。

last_ack:

這個狀態還是比較容易好理解的,它是被動關閉一方在傳送fin報文後,最後等待對方的ack報文。當收到ack報文後,也即可以進入到closed可用狀態了。

TCP連線狀態詳解

下面是每乙個tcp連線在任意時刻可能處於的狀態,在linux下可以在netstat命令的最後一列 state列 裡看到。各個狀態的含義如下 closed 初始狀態,表示tcp連線是 關閉著的 或 未開啟的 listen 表示伺服器端的某個socket處於監聽狀態,可以接受客戶端的連線。syn rcv...

TCP連線狀態詳解

closed 表示初始狀態。listen 表示伺服器端的某個socket處於監聽狀態,可以接受連線。syn sent 在服務端監聽後,客戶端socket執行connect連線時,客戶端傳送syn報文,此時客戶端就進入 syn sent狀態,等待服務端的確認 syn rcvd 表示服務端接受到了syn...

TCP連線狀態描述

狀 態 說 明 closed 不存在tcp連線 listen 乙個應用層協議已經發布了乙個被動開啟,並且有意接收 tcp連線試圖 syn sent 乙個應用層協議已經傳送了乙個主動開啟,並且傳送了乙個 syn段 syn rcvd 乙個syn 段被接收,並且乙個 syn ack 被傳送 establi...