最近寫了乙個程序,需要通過20個執行緒迴圈600個使用者獲取每乙個使用者的xx資訊,是通過socket連線oracle mdb伺服器獲取的,但是在本機windows上測試發現大量的time_wait狀態,按照網上的說法,調了登錄檔的引數,但是無濟於事,socket.setreuseaddress方法也是沒有效果,最後放棄了,在測試環境的unix上也是一樣,但是沒有去調節測試環境的引數,最後直接上了生產,生產上的引數應該是設定過的,最後複習了下這個經典的time_wait狀態狀態
tcp建立連線需要3個握手,但是關閉連線需要4個握手,關閉連線後主動關閉的一方會處於time_wait狀態一段時間,這個是可以設定的,好像windows最少是30s,這個time_wait狀態的目的大概有兩個
1。防止上一次連線中的包,迷路後重新出現,影響新連線
(經過2msl,上一次連線中所有的重複包都會消失)
2。可靠的關閉tcp連線
在主動關閉方傳送的最後乙個 ack(fin) ,有可能丟失,這時被動方會重新發
fin, 如果這時主動方處於 closed 狀態 ,就會響應 rst 而不是 ack。所以
主動方要處於 time_wait 狀態,而不能是 closed
這是tcp關閉連線的client/server直接的資料互動過程
還有一種close_wait
在客戶端主動關閉時,伺服器端也要被動關閉(伺服器端也要主動呼叫closesocket),如果伺服器端不被動關閉,客戶端就收不到伺服器端發來 的fin,就一直在fin_wait_2了,而此時伺服器端只收到客戶端發來的fin(自己只向客戶端發了ack,沒有向客戶端發fin),也一直停留在 close_wait
出現大量close_wait的現象,主要原因是某種情況下對方關閉了socket鏈結,但是我方忙與讀或者寫,沒有關閉連線。**需要判斷socket,一旦讀到0,斷開連線,read返回負,檢查一下errno,如果不是again,就斷開連線。
解決方法
基本的思想就是要檢測出對方已經關閉的socket,然後關閉它。
可以參考tomcat server 原始碼如何檢測client 關閉了socket,server端的socket可以迴圈的read,一旦出現timeout異常就可以關閉了
關於TCP主動關閉連線中的wait timeout
首先我們先來回顧一下tcp關閉連線的過程 假設a和b連線狀態為est,a需要主動關閉 a傳送fin給b,並將狀態更改為fin wait1,b接收到fin將狀態更改為close wait,並回覆ack和fin a收到ack後將狀態更改為fin wait2,收到fin後,更改狀態為wait timeou...
關閉tcp連線
luolei localhost sudo netstat a grep ssh tcp 0 0 192.168.1.10 40278 com ssh established unix 2 acc stream listening 7565 tmp ssh uyvolk4882 agent.4882...
關閉TCP連線
從tcp協議角度來看,乙個已建立的tcp連線有兩種關閉方式,一種是正常關閉,即四次揮手關閉連線 還有一種則是異常關閉,我們通常稱之為連線重置 reset 首先說一下正常關閉時四次揮手的狀態變遷,關閉連線的主動方狀態變遷是fin wait 1 fin wait 2 time wait,而關閉連線的被動...