
上圖爲TCP狀態變遷,其各個狀態含義以下:
- CLOSE:狀態機初始狀態;
- LISTEN:被動打開,服務器端的狀態變爲LISTEN(監聽);
- 被動打開:鏈接的一端的應用程序通知操做系統,但願創建一個傳入的鏈接。這時候操做系統爲這一端創建一個鏈接;
- 主動鏈接:應用程序經過主動打開請求來告訴操做系統創建一個鏈接;
- SYN_RCVD:服務器端收到SYN後,狀態爲SYN,發送SYN ACK;
- SYN_SENT:應用程序發送SYN後,狀態爲SYN_SENT;
- ESTABLISHED:SYN_RCVD收到ACK後,狀態變爲ESTABLISHED;SYN_SENT在收到SYN ACK,發送ACK後,狀態變爲ESTABLISHED;
- CLOSE_WAIT:服務器端在收到FIN後,發送ACK,狀態變爲CLOSE_WAIT;若是此時服務器端還有數據要發送,那麼就發送,直到數據發送完畢,此時服務器發送FIN,狀態變爲LAST_ACK;
- FIN_WAIT_1:應用程序端發送FIN,準備斷開TCP鏈接,狀態從ESTABLISHED->FIN_WAIT_1;
- FIN_WAIT_2:應用程序端只收到服務器端的ACK,並無收到FIN,說明服務器還有數據要傳輸,那麼此時爲半鏈接;
- TIME_WAIT:有以下兩種方式進入該狀態。TIME_WAIT是爲了實現TCP全雙工鏈接的可靠性關閉,用來重發可能丟失的ACK報文;須要持續2個MSL(最大報文生存時間)時間;假設應用程序端口在進入TIME_WAIT後,2個MSL後並無收到FIN,說明應用程序最後發出的ACK已經被收到了;不然,會在2個MSL內再次收到ACK報文。
- FIN_WIAT_1狀態進入:此時應用程序端口收到FIN ACK(而不是像FIN_WAIT_2那樣只收到ACK,說明數據已發送完畢)並向服務器端發送ACK;
- FIN_WAIT_2狀態進入:此時應用程序端口收到FIN,而後向服務器端發送ACK;
客戶端應用程序的狀態遷移路線:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
以上流程是在程序正常的狀況下應該有的流程,從上圖中能夠看到,在創建鏈接時,當客戶端收到SYN報文的ACK之後,客戶端就打開了數據交互地鏈接。而結束鏈接則一般是客戶端主動結束的,客戶端結束應用程序之後,須要經歷FIN_WAIT_1,FIN_WAIT_2等狀態。
服務器的狀態遷移路線:
CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
在創建鏈接的時候,服務器端是在第三次握手以後才進入數據交互狀態,而關閉鏈接則是在關閉鏈接的第二次握手之後(注意不是第四次)。而關閉之後還要等待客戶端給出最後的ACK包才能進入初始的狀態。
其餘狀態遷移:
上圖中還有一些其餘的狀態遷移,這些狀態遷移針對服務器和客戶端兩方面的總結以下 :
-
- LISTEN->SYN_SENT,對於這個解釋就很簡單了,服務器有時候也要打開鏈接的嘛。
- SYN_SENT->SYN_RCVD,服務器和客戶端在SYN_SENT狀態下若是收到SYN數據報,則都須要發送SYN的ACK數據報並把本身的狀態調整到SYN_RCVD狀態,準備進入ESTABLISHED
- SYN_SENT->CLOSED,在發送超時的狀況下,會返回到CLOSED狀態。
- SYN_RCVD->LISTEN,若是受到RST包,會返回到LISTEN狀態。
- SYN_RCVD->FIN_WAIT_1,這個遷移是說,能夠不用到ESTABLISHED狀態,而能夠直接跳轉到 FIN_WAIT_1狀態並等待關閉。