简体   繁体   English

Java网络服务器和TIME_WAIT

[英]Java network server and TIME_WAIT

I have run into a problem with a network server that receives signals from devices my company produces. 我从公司生产的设备接收信号的网络服务器遇到问题。 The device will occasionally reuse the source port that it had just used. 该设备有时会重用它刚使用的源端口。 This causes the SYN to be dropped by the server. 这将导致服务器丢弃SYN。 The device then retries until the old socket falls out of TIME_WAIT on the server. 然后,设备重试,直到旧套接字从服务器上的TIME_WAIT中退出。 The server then SYN-ACKs. 然后,服务器进行SYN-ACK。

The server is written in Java. 服务器是用Java编写的。 Unfortunately, modifying the device to cycle ports correctly is not an option, as there are many in the field, and updating the existing units is not an option. 不幸的是,修改该设备以正确地循环端口是不可行的,因为该字段中有很多设备,而更新现有设备则不是可选的。 The old software was written in C++ and somehow expunged the TIME_WAIT port from the list in the Windows TCP stack. 旧软件是用C ++编写的,并且以某种方式从Windows TCP堆栈的列表中删除了TIME_WAIT端口。

Can anyone offer me any advice on how to circumvent TIME_WAIT from Java on Windows? 谁能为我提供关于如何在Windows上通过Java规避TIME_WAIT的任何建议?

EDIT: I have indeed confirmed in Wireshark that the device is reusing a recently used port. 编辑:我确实在Wireshark中确认了该设备正在重新使用最近使用的端口。

On the server socket I am using the following options: 在服务器套接字上,我使用以下选项:

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);

And the client socket has the following set after receiving: 接收后,客户端套接字具有以下设置:

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

I have tried SO_LINGER as both true and false, with the exact same trace results. 我尝试将SO_LINGER设置为true和false,并获得完全相同的跟踪结果。 CLIENT_READ_TIMEOUT is set to 10 seconds. CLIENT_READ_TIMEOUT设置为10秒。

Building on Nikolai's answer, 以尼古拉的答案为基础,

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

would be the equivalent in Java. 在Java中将是等效的。

EDIT: Another thing you might like to look at would be setReuseAddress(true); 编辑:您可能想看的另一件事是setReuseAddress(true);。

The old not-recommended trick to avoid TIME_WAIT is to set SO_LINGER socket option to { 1, 0 } - the close then sends RST instead of doing normal flush/four-way exchange sequence, thus avoiding the TIME_WAIT all together (be warned - you might lose tail of what you still have in the send buffer.) I can't comment on whether this could be done in Java though. 避免TIME_WAIT的旧的不推荐的技巧是将SO_LINGER套接字选项设置为{ 1, 0 } - close然后发送RST而不是执行正常的刷新/四路交换序列,从而避免一起使用TIME_WAIT (警告-您-可能会丢失发送缓冲区中仍然没有的内容。)尽管如此,我无法评论是否可以在Java中完成。

EDIT: Can you confirm with tcpdump that the clients really reuse source port numbers? 编辑:您可以与tcpdump确认客户端真正重用源端口号吗? If not, this might just be the classic case for SO_REUSEADDR listening socket option as Jon pointed out. 如果不是这样,正如乔恩指出的那样,这可能只是SO_REUSEADDR侦听套接字选项的经典案例。

The server is ignoring the SYN packets from the client because it cannot distinguish between those for a new session using the old source port and retransmissions from the old session. 服务器将忽略来自客户端的SYN数据包,因为它无法区分使用旧源端口的新会话的数据包和来自旧会话的重传数据。 If you circumvent the TIME_WAIT state on the server, by setting the system timer interval for aging out TIME_WAIT state entries in the control block table, then how will your server properly ignore SYN retransmissions for sessions that have already terminated? 如果你避开TIME_WAIT ,通过设置在控制块表老化了TIME_WAIT状态条目系统计时器的时间间隔在服务器上的状态,那么如何将您的服务器正确地忽略那些已经终止会话SYN重传?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM