端口狀態說明 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

 

 

 

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

2.1 總結圖

左邊為客戶端的狀態轉變,后邊為服務器的狀態轉變

 

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這樣看到的包比較集中)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM