天天看點

端口狀态說明 LISTENING、ESTABLISHED、TIME_WAIT及CLOSE_WAIT

TCP狀态轉移要點

    TCP協定規定,對于已經建立的連接配接,網絡雙方要進行四次握手才能成功斷開連接配接,如果缺少了其中某個步驟,将會使連接配接處于假死狀态,連接配接本身占用的資源不會被釋放。網絡伺服器程式要同時管理大量連接配接,是以很有必要保證無用連接配接完全斷開,否則大量僵死的連接配接會浪費許多伺服器資源。在衆多TCP狀态中,最值得注意的狀态有兩個:CLOSE_WAIT和TIME_WAIT。  

1、LISTENING狀态

  FTP服務啟動後首先處于偵聽(LISTENING)狀态。

2、ESTABLISHED狀态

  ESTABLISHED的意思是建立連接配接。表示兩台機器正在通信。

3、CLOSE_WAIT

    對方主動關閉連接配接或者網絡異常導緻連接配接中斷,這時我方的狀态會變成CLOSE_WAIT 此時我方要調用close()來使得連接配接正确關閉

4、TIME_WAIT

    我方主動調用close()斷開連接配接,收到對方确認後狀态變為TIME_WAIT。TCP協定規定TIME_WAIT狀态會一直持續2MSL(即兩倍的分段最大生存期),以此來確定舊的連接配接狀态不會對新連接配接産生影響。處于TIME_WAIT狀态的連接配接占用的資源不會被核心釋放,是以作為伺服器,在可能的情況下,盡量不要主動斷開連接配接,以減少TIME_WAIT狀态造成的資源浪費。

    目前有一種避免TIME_WAIT資源浪費的方法,就是關閉socket的LINGER選項。但這種做法是TCP協定不推薦使用的,在某些情況下這個操作可能會帶來錯誤。

1. socket的狀态

1.1 狀态說明

CLOSED 沒有使用這個套接字[netstat 無法顯示closed狀态]
LISTEN 套接字正在監聽連接配接[調用listen後]
SYN_SENT 套接字正在試圖主動建立連接配接[發送SYN後還沒有收到ACK]
SYN_RECEIVED 正在處于連接配接的初始同步狀态[收到對方的SYN,但還沒收到自己發過去的SYN的ACK]
ESTABLISHED 連接配接已建立
CLOSE_WAIT 遠端套接字已經關閉:正在等待關閉這個套接字[被動關閉的一方收到FIN]
FIN_WAIT_1 套接字已關閉,正在關閉連接配接[發送FIN,沒有收到ACK也沒有收到FIN]
CLOSING 套接字已關閉,遠端套接字正在關閉,暫時挂起關閉确認[在FIN_WAIT_1狀态下收到被動方的FIN]
LAST_ACK 遠端套接字已關閉,正在等待本地套接字的關閉确認[被動方在CLOSE_WAIT狀态下發送FIN]
FIN_WAIT_2 套接字已關閉,正在等待遠端套接字關閉[在FIN_WAIT_1狀态下收到發過去FIN對應的ACK]
TIME_WAIT 這個套接字已經關閉,正在等待遠端套接字的關閉傳送[FIN、ACK、FIN、ACK都完畢,這是主動方的最後一個狀态,在過了2MSL時間後變為CLOSED狀态]

1.2 狀态變遷圖

摘自《UNIX 網絡程式設計 卷1:套接字聯網API》 P35
端口狀态說明 LISTENING、ESTABLISHED、TIME_WAIT及CLOSE_WAIT

2. TCP的三次握手和四次揮手

2.1 總結圖

左邊為用戶端的狀态轉變,後邊為伺服器的狀态轉變
端口狀态說明 LISTENING、ESTABLISHED、TIME_WAIT及CLOSE_WAIT

2.2 說明

2.2.1   connect傳回-1

             errno=110(ETIMEDOUT),當伺服器端網線拔了的時候,用戶端發送SYN過去就會收不到ACK,是以就會出現這個錯誤,1分鐘内就會返  回這個錯誤。

             errno=111(ECONNREFUSED),當伺服器未listen時,就會報這個錯

2.2.2 ESTABLISHED不一定真的establish

              會出現這種情況:client為ESTABLISHED狀态而server為SYN_REVD狀态。

             這是因為LINUX不像其他作業系統在收到SYN為該連接配接立馬配置設定一塊記憶體空間用于存儲相關的資料和結構,而是延遲到接收到client的ACK,即三次握手    真正完成後才配置設定空間,這是為了防範SYN flooding攻擊。 如果是這種情況,那麼就會出現client端未ESTABLISHED狀态,server為SYN_RECV狀态。   

             并且server的SYN_RECV狀态在一定時間後會消失,client的established狀态也會消失。這是因為server在SYN_RECV狀态時,會像client發送多次的SYN+ACK(因為他以為自己的這個包對方沒收到),發送的次數定義在/proc/sys/net/ipv4/tcp_synack_retries中,預設為5.在發送5次之後還沒有收到ACK,就将其回收了,是以用netstat檢視就看不到這個SYN_RECV狀态了。并且會像client發送RST信号。這就會導緻client的這種半連接配接最後也會消失。這個可以通過tcpdump抓包得到(最好知道src這樣看到的包比較集中)。

繼續閱讀