[轉載]TCP狀態機-狀態解析

--------------------- 
作者:天天向上_好好學習 
原文:https://blog.csdn.net/cheng_fangang/article/details/23183173 

 

在網絡協議棧中, 目前只有tcp提供了一種面向連接的可靠性數據傳輸。 而可靠性,無非就是保證,我發給你的,你一定要收到。確保中間的通信過程中,不會丟失數據和亂序。 在TCP保證可靠性數據傳輸的實現來看, 超時重傳、序列號及數據的應答 這三個特徵 就是實現可靠性的最基本保證,而對於tcp窗口大小等等設置,也是保證可靠性的一個方面。所有的目的只爲一個,保證傳輸數據的完整性。 爲了解決傳輸線路的不穩定性造成數據包的丟失情況,tcp 使用了發送方超時重傳和接收方數據應答的策略。概括而言,就是一種“狀態協議“,保證通信雙方數據收發的一致性。

藉助網上的一個狀態圖

下面簡析一下 TCP的各個狀態。

TCP_CLOSE:關閉狀態, 一個新建的TCP socket 會處於該狀態。

TCP_LISTEN: 監聽狀態,一般服務器端套接字在調用Listen系統調用後即處於該狀態。

TCP_SYN_SENT:同步信號已經發送狀態,這個狀態一般是指客戶端發送SYN(建立連接的同步)數據包後所處的狀態(tcp三次握手的第一個包)。在接收到遠端服務器端的應答後,即從該狀態進入TCP_ESTABLISHED狀態。

TCP_SYN_RECEIVED:同步信號已經接受狀態,服務器端在接受到遠端客戶端SYN數據包後,進行相應的處理(創建通信套接字等),然後發送應答數據包(tcp三次握手的第二個包),並將新創建的通信套接字狀態設置爲TCP_SYN_RECEIVED,在接受到客戶端的應答後,即進入TCP_ESTABLISED狀態。

TCP_ESTABLISED:建立連接狀態,這是雙方進行正常通信所處的狀態。

TCP_FIN_WAIT_1:本地發送FIN(用於結束連接的)數據包後即可進入該狀態,等待對方的應答。一般一端發送完其所要發送的數據後,即可發送FIN數據包,此時發送通道被關閉,但仍可繼續接受遠端發送的數據包。在接受到遠端發送的對於FIN數據包的應答後,將進入TCP_FIN_WAIT_2狀態。

TCP_FIN_WAIT_2:進入該狀態表示本地已經接受到遠端發送的對於本地之前發送的FIN數據包的應答。進入該狀態後,本地仍然可以繼續接受遠端發送給笨的的數據包。在接受到遠端發送的FIN數據包後(表示遠端也已經發送完數據),本地將發送一個應答數據包,並進入TCP_TIME_WAIT狀態。TCP_TIME_WAIT狀態存在的時間被稱爲2MSL時間,這一方面是爲避免本地發送的應答數據包丟失,另一方面避免一個新創建的套接字接收到舊套接字中遺留的數據包。

TCP_TIME_WAIT:該轉狀態唄稱爲2MSL等待狀態。如果在此期間接收到遠端發送的FIN數據包,則表示之前在TCP_FIN_WAIT_2狀態發送的ACK應答數據包在傳輸中丟失或者長時間被延遲,從而造成了遠端重新發送了FIN數據包,此時重複ACK應答數據包。一旦2MSL時間到期,則將進入TCP_CLOSED狀態,即完成關閉操作。

TCP_CLOSE_WAIT:該狀態存在於後關閉的一端。當接收到遠端發送的FIN數據包後,本地發送一個ACK應答數據包,並將該套接字狀態從TCP_ESTABLISED設置爲TCP_CLOSE_WAIT。本地可以繼續向遠端發送數據包,在發送完所有的數據後,本地將發送一個FIN數據包關閉本地發送通道,並將狀態設置爲TCP_LAST_ACK狀態,等待遠端對FIN數據包的應答數據包。

TCP_CLOSING:如果通信雙方同時發送FIN數據包,則同時進行關閉操作,則雙方將同時進入TCP_CLOSING狀態。具體的,本地發送一個FIN數據包以結束本地數據包發送,如果在等待應答期間,接收到遠端發送的FIN數據包,則本地將狀態設置爲TCP_CLOSING狀態。在接收到應答後,再繼續裝入到TCP_CLOSE_WAIT狀態。

TCP_LAST_ACK:作爲後關閉的一方,在發送FIN數據包後,即進入TCP_LAST_ACK狀態。此時等待遠端發送應答數據包,在接收到應答數據包後,即完成關閉操作,進入TCP_CLOSE狀態。

下面的代碼是對應的狀體。

enum {
  TCPF_ESTABLISHED = (1 << 1),
  TCPF_SYN_SENT  = (1 << 2),
  TCPF_SYN_RECV  = (1 << 3),
  TCPF_FIN_WAIT1 = (1 << 4),
  TCPF_FIN_WAIT2 = (1 << 5),
  TCPF_TIME_WAIT = (1 << 6),
  TCPF_CLOSE     = (1 << 7),
  TCPF_CLOSE_WAIT = (1 << 8),
  TCPF_LAST_ACK  = (1 << 9),
  TCPF_LISTEN    = (1 << 10),
  TCPF_CLOSING   = (1 << 11) 
};


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章