Java网络服务器和TIME_WAIT

时间:2009-05-28 20:21:52

标签: java networking sockets

我遇到了网络服务器的问题,该网络服务器接收来自我公司生产的设备的信号。该设备偶尔会重用它刚才使用的源端口。这会导致服务器删除SYN。然后,设备将重试,直到旧套接字在服务器上超出TIME_WAIT。服务器然后SYN-ACKs。

服务器是用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作为true和false,具有完全相同的跟踪结果。 CLIENT_READ_TIMEOUT设置为10秒。

3 个答案:

答案 0 :(得分:5)

以尼古拉的回答为基础,

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

在Java中是等效的。

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

答案 1 :(得分:3)

要避免TIME_WAIT的旧不推荐技巧是将SO_LINGER套接字选项设置为{ 1, 0 } - close然后发送{{ 1}}而不是正常的刷新/四向交换序列,从而避免RST所有在一起(被警告 - 你可能会丢失你在发送缓冲区中仍然拥有的东西。)我无法发表评论是否可以用Java完成。

编辑:您能否与TIME_WAIT确认客户真正重用源端口号?如果没有,这可能只是Jon指出的SO_REUSEADDR监听套接字选项的经典案例。

答案 2 :(得分:0)

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