2009-05-28 59 views
1

我遇到了接收來自我公司設備產生的信號的網絡服務器的問題。該設備偶爾會重複使用剛纔使用的源端口。這會導致服務器丟棄SYN。然後設備重試,直到舊的套接字不在服務器上的TIME_WAIT中。服務器然後SYN-ACK。Java網絡服務器和TIME_WAIT

服務器是用Java編寫的。不幸的是,修改設備以正確循環端口不是一種選擇,因爲現場有許多設備,更新現有設備不是一種選擇。舊軟件以C++編寫,並以某種方式從Windows TCP堆棧中的列表中刪除了TIME_WAIT端口。

任何人都可以提供任何關於如何在Windows上從Java規避TIME_WAIT的建議嗎?

編輯:我確實在Wireshark中確認設備正在重新使用最近使用的端口。

服務器套接字我使用下列選項:

socket = new ServerSocket(); 
socket.setPerformancePreferences(3, 2, 1); 
socket.setReuseAddress(true); 
socket.setSoTimeout(CLIENT_READ_TIMEOUT); 
socket.bind(new InetSocketAddress(group.getPort()), MAX_TCP_BACKLOG); 

而且客戶端套接字有以下設置接收後:

Socket client = server.accept(); 
client.setKeepAlive(false); 
client.setSoLinger(true, 0); 
client.setReuseAddress(true); 
client.setTcpNoDelay(true); 
client.setSoTimeout(CLIENT_READ_TIMEOUT); 

我試圖SO_LINGER既是真與假,具有完全相同的跟蹤結果。 CLIENT_READ_TIMEOUT設置爲10秒。

回答

3

不推薦辦法來避免TIME_WAITSO_LINGER套接字選項設置爲{ 1, 0 } - 在close然後發送RST而不是做正常的沖洗/四路交換序列,從而避免了TIME_WAIT一起(被警告 - 你可能會失去在發送緩衝區中仍然存在的東西)。我不能評論這是否可以在Java中完成。

編輯:你可以用tcpdump確認客戶端真正重用源端口號嗎?如果不是的話,這可能就是Jon指出的SO_REUSEADDR監聽套接字選項的經典案例。

4

大廈尼古拉的回答,

Socket s; 
... 
s.setSoLinger(true,0); 

將在Java中的等價物。

編輯:你可能會喜歡看的另一件事是setReuseAddress(true);

0

服務器忽略來自客戶端的SYN數據包,因爲它無法區分使用舊源端口的新會話和舊會話的重傳。如果您繞過服務器上的TIME_WAIT狀態,通過設置控制塊表中TIME_WAIT狀態條目的系統定時器間隔,那麼您的服務器如何正確忽略已重新結束的會話的SYN重傳?