我遇到了网络服务器的问题,该网络服务器接收来自我公司生产的设备的信号。该设备偶尔会重用它刚才使用的源端口。这会导致服务器删除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秒。
答案 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重新传输?