Java网络服务器和时间等待

Java网络服务器和时间等待,java,networking,sockets,Java,Networking,Sockets,我遇到了一个网络服务器的问题,该服务器接收来自我公司生产的设备的信号。设备偶尔会重用它刚刚使用的源端口。这会导致服务器删除SYN。然后,设备将重试,直到旧套接字在服务器上的等待时间超时。然后服务器将同步确认 服务器是用Java编写的。不幸的是,修改设备以正确循环端口不是一个选项,因为现场有很多,更新现有设备也不是一个选项。旧软件是用C++编写的,并且在Windows TCP堆栈中从列表中删除了TimeIOFAUTE端口。 有谁能给我一些建议,告诉我如何在Windows上避开Java的等待时间 编

我遇到了一个网络服务器的问题,该服务器接收来自我公司生产的设备的信号。设备偶尔会重用它刚刚使用的源端口。这会导致服务器删除SYN。然后,设备将重试,直到旧套接字在服务器上的等待时间超时。然后服务器将同步确认

服务器是用Java编写的。不幸的是,修改设备以正确循环端口不是一个选项,因为现场有很多,更新现有设备也不是一个选项。旧软件是用C++编写的,并且在Windows TCP堆栈中从列表中删除了TimeIOFAUTE端口。 有谁能给我一些建议,告诉我如何在Windows上避开Java的等待时间

编辑:我确实在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);
我试过把Sou LINGER看作是真是假,跟踪结果完全相同。客户端读取超时设置为10秒。

避免
等待时间的老技巧是将
设置为
,以便将
套接字选项设置为
{1,0}
关闭
然后发送
RST
,而不是执行正常的刷新/四向交换顺序,从而避免了
等待时间
(请注意,您可能会丢失发送缓冲区中仍然存在的内容的详细信息。)不过,我无法评论这是否可以在Java中完成。

编辑:你能用
tcpdump
确认客户端是否真的重用了源端口号吗?如果不能,这可能就是Jon指出的SO_REUSEADDR侦听套接字选项的典型情况。

避免
等待时间的老技巧是将
SO_LINGER
套接字选项设置为
{1,0}
-关闭
然后发送
RST
,而不是执行正常的刷新/四路交换顺序,从而避免了
等待时间
(请注意,您可能会丢失发送缓冲区中的信息。)不过,我无法评论是否可以在Java中完成此操作。


编辑:你能用
tcpdump
确认客户端是否真的重用了源端口号吗?如果不能,这可能就是Jon指出的SO_REUSEADDR侦听套接字选项的典型例子。

基于Nikolai的回答

Socket s;
...
s.setSoLinger(true,0);
在Java中是等效的


编辑:另一件你可能想看的东西是setReuseAddress(true);

基于尼古拉的答案

Socket s;
...
s.setSoLinger(true,0);
在Java中是等效的


编辑:另一个您可能想查看的内容是setReuseAddress(true);

服务器忽略来自客户端的SYN数据包,因为它无法区分使用旧源端口的新会话的SYN数据包和从旧会话重新传输的SYN数据包。如果您绕过服务器上的
TIME\u WAIT
状态,请为控件中的老化超时等待状态项设置系统计时器间隔块表,那么您的服务器将如何正确地忽略已终止会话的SYN重新传输?

服务器将忽略来自客户端的SYN数据包,因为它无法区分使用旧源端口的新会话的SYN数据包和来自旧会话的重新传输。如果您绕过
时间,\u WAIT服务器上的状态,通过在控制块表中设置老化超时\u等待状态项的系统计时器间隔,那么服务器如何正确忽略已终止会话的SYN重新传输