客户端套接字被服务器关闭,然后客户端在同一端口上打开新套接字时出现JVM_Bind错误

时间:2012-07-06 13:33:01

标签: java windows sockets tcp

此问题是间歇性的,每30小时运行一次,每隔几个小时发生一次,并执行以下网络通信:

  • 远程计算机上有服务器正在侦听
  • 客户端连接到此计算机并告知服务器连接回该计算机
  • 服务器< / b>关闭套接字并重新连接到客户端
  • 当套接字在客户端关闭时,客户端立即开始侦听同一端口

当客户端尝试开始侦听同一端口时,会在客户端上发生JVM_Bind错误,即使它仅在原始套接字关闭后尝试执行此操作。在套接字关闭和打开新套接字之间添加100毫秒的轻微延迟可以防止JVM_Bind错误。

我可以使用哪些工具来调试此方案?运行连续的netstat没有显示任何干扰端口的事情。

即使在同一个端口上启动一个新套接字是一个坏主意,为什么会间歇性地发生这个错误呢?

编辑:一些其他信息。服务器从服务器上的临时端口连接回客户端。客户端的旧套接字将直接进入CLOSED并且应该能够重新打开。难道不可能是OS,JVM或硬件上发生的事情吗?

2 个答案:

答案 0 :(得分:1)

来自Docs

当TCP连接关闭时,连接可能会在连接关闭后的一段时间内保持超时状态(通常称为TIME_WAIT状态或2MSL等待状态)。对于使用众所周知的套接字地址或端口的应用程序,如果在涉及套接字地址或端口的超时状态中存在连接,则可能无法将套接字绑定到所需的SocketAddress。

为什么它会进入这种状态详细here

This is how it enters the TIME_WAIT state

现在每次断开套接字时都不会发生这种情况,这就是为什么问题可能是断断续续的原因。

在使用bind(SocketAddress)绑定套接字之前启用SO_REUSEADDR允许套接字绑定,即使先前的连接处于超时状态。

socket.setReuseAddress(true);

答案 1 :(得分:1)

在搞乱这个问题后,我们最终运行了Wireshark和Procmon来监控TCP连接和数据包。 Procmon是用于调试Windows上的问题的非常好的工具,可以配置为显示何时创建和删除TCP连接。 Wireshark显示跨越线路的实际分组数据。此输出显示事件正在进行,因为它们应该在JVM_Bind错误发生时。日志在工作时和失败时之间没有实质性差异。

这指责了系统。我考虑了系统设置,然后把注意力转向了驱动程序问题的可能性。更新了网络适配器驱动程序,问题已经消失。

故事的道德是使用Wireshark和Procmon调试网络问题,它将此问题转化为可分析的问题。