TCP状态机详解
一、TCP狀態機是TCP連接的變化過程。
Tcp在三次握手和四次揮手的過程,就是一個tcp的狀態說明,由于tcp是一個面向連接的,可靠的傳輸,每一次的傳輸都會經歷連接,傳輸,關閉的過程,無論是哪個方向的傳輸,必須建立連接才行,在雙方通信的過程中,tcp 的狀態是不一樣的。
下面介紹一下,在三次握手和四次揮手的過程中的幾種狀態,如下圖所示,是tcp狀態的變化過程
?
各種狀態的解釋
LISTEN:偵聽來自遠方TCP端口的連接請求
SYN-SENT:發送連接請求后等待匹配的連接請求
SYN-RECEIVED(syn已經收到的):收到和發送給一個連接請求后等待對連接請求的確認
ESTABLISHED(已建立的):代表一個打開的連接,數據可以傳送給客戶
FIN-WAIT-1:等待遠程TCP的連接中斷請求,或者先前的連接中斷請求的確認
FIN-WAIT-2:從遠程TCP等待連接中斷請求
CLOSE-WAIT:等待從本地用戶發來的連接中斷請求
CLOSEING:等待遠程TCP對連接中斷的確認
LAST-ACK:等待原來發向遠程TCP的連接中斷請求的確認
TIME-WAIT:等待足夠的時間一確保遠程TCP接受到連接中斷請求的確認
CLOSED:沒有任何連接狀態
下圖是時序圖
?
二、tcp建立連接的三次握手和四次揮手。
?
客戶方主動打開TCP連接,向另一端的服務器方發送一個SYN同步序號來請求發起一個連接,客戶方發送SYN后會變為SYN_SENT狀態,這種狀態時等待對端回應狀態。
再看服務器端,服務器作為被動打開方回收到客戶方發來的SYN連接請求信息(在圖中為SYN j),服務器收到SYN請求后本身狀態會從監聽LISTEN狀態轉化到SYN_RCVD狀態,會發送一個與收到的SYN相對應的ACK確認序號有效信息(圖中ACK j+1)和自身向對端請求連接的同步序號SYN(在圖中為SYN k)。
處于SYN_SENT狀態的客戶方一直等待著對端回應ACK信息和SYN信息,當收到回應信息后客戶方的狀態會從SYN_SENT狀態轉換到ESTABLISHED,此時客戶方能夠進行雙向數據傳遞,向對端發送一個服務器發來的SYN相對應的ACK信息(及圖中的ACK k+1)。如果客戶方一直沒有收到回應信息,客戶方的SYN_SENT狀態會超時重新回到初始狀態。
服務器方收到客戶方發來的ACK回應信息后會從先前的SYN接收狀態SYN_RCVD轉換到ESTABLISHED,之后服務器方也能夠進行雙向數據傳遞。當TCP連接的雙方都進入ESTABLISHED狀態后,這個TCP連接便建立成功了,連接雙方都能夠進行雙向數據傳輸。
當通信雙方通信結束需要終止TCP連接,再此假定客戶方發起主動關閉,此時客戶方會向服務器方發送FIN完成數據發送信息(圖中FIN m),客戶方發送FIN信息后狀態會從ESTABLISHED數據傳輸狀態轉換到FIN_WAIT_1狀態,等待服務器方返回的確認信息。
服務器方收到客戶方發來的FIN信息后狀態會由ESTABLISHED數據傳輸狀態轉換到CLOSE_WAIT狀態。檢查自身的數據發送狀態,如果此時還有數據在發送,服務器方會先回復客戶方一個與收到的FIN信息相對應的ACK確認信息(圖中ACK m+1),等到自身數據發送結束之后再次向客戶方發送一個自己的FIN完成數據發送信息(圖中FIN n),之后狀態再次轉換到LAST_ACK狀態;如果此時檢查自身的數據也發送結束,會向客戶方同時發送ACK和FIN信息,狀態再次轉換到LAST_ACK狀態。
客戶方的狀態是由收到信息來決定的。當只收到服務器方給自己的ACK確認信息,客戶方的狀態會從FIN_WAIT_1狀態轉換成FIN_WAIT_2狀態。這時候只有一方進程關閉,就進入了半連接狀態,只有另一端數據傳輸完成也發來FIN信息,狀態才會轉換到TIME_WAIT狀態;當同時收到服務器方發來ACK信息和服務器自己的FIN信息時,客戶方的狀態會從FIN_WAIT_1直接轉換到TIME_WAIT狀態。
服務器方收到客戶方發給自己的ACK確認信息后,服務器方的狀態會從LAST_ACK狀態轉換成初始狀態CLOSED 。
客戶方收到對方的FIN信息后,將狀態轉換到TIME_WAIT狀態,會回復給服務器方一個對應的ACK確認信息(圖中ACK n+1),同時客戶方會在這個狀態停留2MSL時間以防止最后發出的ACK丟失,服務器方再次發起重連。
客戶端tcp狀態遷移
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
服務器TCP狀態遷移:
CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
三、TCP/IP協議中采用三次握手建立一個連接為TCP協議提供可靠的連接服務。
(1)第一次握手:建立連接時,客戶端A發送SYN包(SYN=j)到服務器B,并進入SYN_SEND狀態,等待服務器B確認。
(2)第二次握手:服務器B收到SYN包,必須確認客戶A的SYN(ACK=j+1),同時自己也發送一個SYN包(SYN=k),即SYN+ACK包,此時服務器B進入SYN_RECV狀態。
(3)第三次握手:客戶端A收到服務器B的SYN+ACK包,向服務器B發送確認包ACK(ACK=k+1),此包發送完畢,客戶端A和服務器B進入ESTABLISHED狀態,完成三次握手。
完成三次握手,客戶端與服務器開始傳送數據。
?
四、安全關閉連接。
由于TCP連接是全雙工的,因此每個方向都必須單獨進行關閉。這個原則是當一方完成它的數據發送任務后就能發送一個FIN來終止這個方向的連接。收到一個 FIN只意味著這一方向上沒有數據流動,一個TCP連接在收到一個FIN后仍能發送數據。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。
TCP的連接的拆除需要發送四個包,因此稱為四次揮手(four-way handshake)。客戶端或服務器均可主動發起揮手動作,在socket編程中,任何一方執行close()操作即可產生揮手操作。
(1)客戶端A發送一個FIN,用來關閉客戶A到服務器B的數據傳送。
(2)服務器B收到這個FIN,它發回一個ACK,確認序號為收到的序號加1。和SYN一樣,一個FIN將占用一個序號。
(3)服務器B關閉與客戶端A的連接,發送一個FIN給客戶端A。
(4)客戶端A發回ACK報文確認,并將確認序號設置為收到序號加1。
?
【問題1】為什么連接的時候是三次握手,關閉的時候卻是四次握手?答:因為當Server端收到Client端的SYN連接請求報文后,可以直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連接時,當Server端收到FIN報文時,很可能并不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴Client端,'你發的FIN報文我收到了'。只有等到我Server端所有的報文都發送完了,我才能發送FIN報文,因此不能一起發送。故需要四步握手。
【問題2】為什么TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?
答:雖然按道理,四個報文都發送完畢,我們可以直接進入CLOSE狀態了,但是我們必須假象網絡是不可靠的,有可以最后一個ACK丟失。所以TIME_WAIT狀態就是用來重發可能丟失的ACK報文。
總結
- 上一篇: git 查看某个文件的历史记录
- 下一篇: Linux环境变量配置