關於網絡設備的FIN_WAIT_2狀態解釋出處:http://hi.baidu.com/netdemon1981/blog/item/584bfbb2aeb1d4acd9335ad9.html
在HTTP應用中,存在一個問題,SERVER由於某種原因關閉連接,如KEEPALIVE的超時,這樣,作為主動關閉的SERVER一方就會進入 FIN_WAIT2狀態,但TCP/IP協議棧有個問題,FIN_WAIT2狀態是沒有超時的(不象TIME_WAIT狀態),所以如果CLIENT不關閉,這個FIN_WAIT_2狀態將保持到系統重新啟動,越來越多的FIN_WAIT_2狀態會致使內核crash。
產生原因:
1。常連接並且當連接一直處於IDLE狀態導致SERVER CLOSE時,CLIENT編程缺陷,沒有向SERVER 發出FIN和ACK包
2。APACHE1.1和APACHE1.2增加了linger_close()函數,前面的帖子有介紹,這個函數可能引起了這個問題(為什么我也不清楚)
解決辦法:
1。對FIN_WAIT_2狀態增加超時機制,這個特性在協議里沒有體現,但在一些OS中已經實現
如:LINUX、SOLARIS、FREEBSD、HP-UNIX、IRIX等
2。不要用linger_close()編譯
3。用SO_LINGER代替,這個在某些系統中還能很好地處理
4。增加用於存儲網絡連接狀態的內存mbuf,以防止內核crash
5。DISABLE KEEPALIVE
TCP FIN_WAIT_2狀態問題分析
出處:http://hi.baidu.com/huochai2020/item/eb3fc2530fb52bd6d48bace5
1、出現fin_wait_2一般為客戶端,如果為服務端出現,則表明是服務端主動發起的斷開。
C:\Documents and Settings\Administrator>netstat -an|findstr 10.208.8.2:
TCP 10.88.2.26:9002 10.208.8.2:1040 FIN_WAIT_2
TCP 10.88.2.26:9002 10.208.8.2:1048 FIN_WAIT_2
TCP 10.88.2.26:9002 10.208.8.2:1051 FIN_WAIT_2
TCP 10.88.2.26:9002 10.208.8.2:1052 FIN_WAIT_2
TCP 10.88.2.26:9002 10.208.8.2:1056 FIN_WAIT_2
TCP 10.88.2.26:9002 10.208.8.2:1058 FIN_WAIT_2 #netstat -an|grep 10.116.50.30
tcp 0 0 192.168.129.44.64306 10.116.50.30.53081 FIN_WAIT_2
tcp 0 0 192.168.129.44.63611 10.116.50.30.57966 FIN_WAIT_2
tcp 0 0 192.168.129.44.57835 10.116.50.30.49188 FIN_WAIT_2
tcp 0 0 192.168.129.44.57502 10.116.50.30.52615 ESTABLISHED
2、為什么發生
a.客戶端狀態遷移(主動結束連接)CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSEDb.服務器狀態遷移CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED 有缺陷的客戶端與持久連接
有一些客戶端在處理持久連接(aka keepalives)時存在問題。當連接空閑下來服務器關閉連接時(基於KeepAliveTimeout指令), 客戶端的程序編制使它不發送FIN和ACK回服務器。這樣就意味着這個連接 將停留在FIN_WAIT_2狀態直到以下之一發生:
客戶端為同一個或者不同的站點打開新的連接,這樣會使它在該個套接字上完全關閉以前的連接。
用戶退出客戶端程序,這樣在一些(也許是大多數?)客戶端上會使操作系統完全關閉連接。
FIN_WAIT_2超時,在那些具有FIN_WAIT_2狀態超時設置的服務器上。
如果你夠幸運,這樣意味着那些有缺陷的客戶端會完全關閉連接並釋放你服務器的資源。 然而,有一些情況下套接字永遠不會完全關閉,比如一個撥號客戶端在關閉客戶端程序之前從ISP斷開。 此外,有的客戶端有可能空置好幾天不創建新連接,並且這樣在好幾天里保持着套接字的有效即使已經不再使用。 這是瀏覽器或者操作系統的TCP實現的Bug。
3、如何解決
為 FIN_WAIT_2 增加 超時機制
windows:
開始->運行->輸入regedit
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
在詳細信息窗格中雙擊 TCPFinWait2Delay ,然后從 30 到 300 中輸入一個值。
請注意 如果不存在 TCPFinWait2Delay 值,必須為 REG _ DWORD 注冊表值來創建它。 注冊表該值控制 TCP 連接之前等待的秒數它被強制關閉, 關閉 (s,SD_SEND) 函數調用之后。 在默認值為 240 秒。 此值范圍是 30 到 300。 必須手動創建此注冊表值。 否則,使用默認值。
HP-UNIX:
#ndd -set /dev/tcp tcp_fin_wait_2_timeout 60000 (1分鍾)
執行上述命令,重起系統后將失效,如果需要一致起作用,則修改下列文件:/etc/rc.config.d/nddconf
設置參數tcp_fin_wait_2_timeout值。
禁止KeepAlive
Apache:編輯你的httpd.conf並把"KeepAlive On"改為"KeepAlive Off"。
使用linger:
linger lig;
lig.l_onoff=1;
lig.l_linger=0;
int ilen=sizeof(linger);
setsockopt(Socket,SOL_SOCKET,SO_LINGER,(char*)&lig,ilen);