串連建立和斷開過程: CLOSED: 表示初始狀態。
LISTEN: 這個也是非常容易理解的一個狀態,表示伺服器端的某個SOCKET處於監聽狀態,可以接受串連了。
SYN_RCVD: 這個狀態表示接受到了SYN報文,在正常情況下,這個狀態是伺服器端的SOCKET在建立TCP串連時的三向交握會話過程中的一個中間狀態,很短暫,基本上用netstat你是很難看到這種狀態的,除非你特意寫了一個用戶端測試程式,故意將三次TCP握手過程中最後一個ACK報文不予發送。因此這種狀態時,當收到用戶端的ACK報文後,它會進入到ESTABLISHED狀態。
SYN_SENT: 這個狀態與SYN_RCVD遙想呼應,當用戶端SOCKET執行CONNECT串連時,它首先發送SYN報文,因此也隨即它會進入到了SYN_SENT狀態,並等待服務端的發送三向交握中的第2個報文。SYN_SENT狀態表示用戶端已發送SYN報文。
ESTABLISHED:這個容易理解了,表示串連已經建立了。
FIN_WAIT_1: 這個狀態要好好解釋一下,其實FIN_WAIT_1和FIN_WAIT_2狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區別是:FIN_WAIT_1狀態實際上是當SOCKET在ESTABLISHED狀態時,它想主動關閉串連,向對方發送了FIN報文,此時該SOCKET即進入到FIN_WAIT_1狀態。而當對方回應ACK報文後,則進入到FIN_WAIT_2狀態,當然在實際的正常情況下,無論對方何種情況下,都應該馬上回應ACK報文,所以FIN_WAIT_1狀態一般是比較難見到的,而FIN_WAIT_2狀態還有時常常可以用netstat看到。
FIN_WAIT_2:上面已經詳細解釋了這種狀態,實際上FIN_WAIT_2狀態下的SOCKET,表示半串連,也即有一方要求close串連,但另外還告訴對方,我暫時還有點資料需要傳送給你,稍後再關閉串連。
TIME_WAIT: 表示收到了對方的FIN報文,並發送出了ACK報文,就等2MSL後即可回到CLOSED可用狀態了。如果FIN_WAIT_1狀態下,收到了對方同時帶 FIN標誌和ACK標誌的報文時,可以直接進入到TIME_WAIT狀態,而無須經過FIN_WAIT_2狀態。
CLOSING: 這種狀態比較特殊,實際情況中應該是很少見,屬於一種比較罕見的例外狀態。正常情況下,當你發送FIN報文後,按理來說是應該先收到(或同時收到)對方的 ACK報文,再收到對方的FIN報文。但是CLOSING狀態表示你發送FIN報文後,並沒有收到對方的ACK報文,反而卻也收到了對方的FIN報文。什麼情況下會出現此種情況呢?其實細想一下,也不難得出結論:那就是如果雙方几乎在同時close一個SOCKET的話,那麼就出現了雙方同時發送FIN報文的情況,也即會出現CLOSING狀態,表示雙方都正在關閉SOCKET串連。
CLOSE_WAIT: 這種狀態的含義其實是表示在等待關閉。怎麼理解呢?當對方close一個SOCKET後發送FIN報文給自己,你系統毫無疑問地會回應一個ACK報文給對方,此時則進入到CLOSE_WAIT狀態。接下來呢,實際上你真正需要考慮的事情是察看你是否還有資料發送給對方,如果沒有的話,那麼你也就可以 close這個SOCKET,發送FIN報文給對方,也即關閉串連。所以你在CLOSE_WAIT狀態下,需要完成的事情是等待你去關閉串連。
LAST_ACK: 這個狀態還是比較容易好理解的,它是被動關閉一方在發送FIN報文後,最後等待對方的ACK報文。當收到ACK報文後,也即可以進入到CLOSED可用狀態了串連的數量和檔案系統的控制代碼有關係用ulimt -n 查看可以通過修改/etc/security/limit.conf設定某使用者的nofile數量在一些高並發的系統中,經常會出現大量的TIME_WAIT和CLOSE_WAIT狀態,下面重點對這兩個狀態進行提出最佳化思路。TIME_WAIT:大量出現這個狀態往往說明系統的並發比較高,大量的串連建立和釋放,可以用長串連方式或者對短串連進行快速的回收/etc/sysctl.conf
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
然後執行
/sbin/sysctl -p 讓參數生效。
net.ipv4.tcp_syncookies = 1 表示開啟SYN Cookies。當出現SYN等待隊列溢出時,啟用cookies來處理,可防範少量SYN攻擊,預設為0,表示關閉;
net.ipv4.tcp_tw_reuse = 1 表示開啟重用。允許將TIME-WAIT sockets重新用於新的TCP串連,預設為0,表示關閉;
net.ipv4.tcp_tw_recycle = 1 表示開啟TCP串連中TIME-WAIT sockets的快速回收,預設為0,表示關閉。
net.ipv4.tcp_fin_timeout 修改系統預設的 TIMEOUT 時間CLOSE_WAIT:Server 程式處於CLOSE_WAIT狀態,而不是LAST_ACK狀態,說明還沒有發FIN給Client,那麼可能是在關閉串連之前還有許多資料要發送或者其他事要做,導致沒有發這個FIN packet,但是用戶端的socket已經斷掉了。
通常來說,一個CLOSE_WAIT會維持至少2個小時的時間。如果有個流氓特地寫了個程式,給你造成一堆的CLOSE_WAIT,消耗
你的資源,那麼通常是等不到釋放那一刻,系統就已經解決崩潰了。
只能通過修改一下TCP/IP的參數,來縮短這個時間:修改tcp_keepalive_*系列參數有助於解決這個問題。