切断连接时,Java套接字不会超时

时间:2014-08-15 16:12:10

标签: java linux sockets timeout xmpp

我看到自动化测试存在一些奇怪的问题。

有以下设置: 服务器:Centos 6 Client1:Windows 7 Client2:Centos 6

我通过阻止服务器iptables上的出站连接来编写模拟连接中断到服务器的测试。但是,socket的行为在Windows上与Linux客户端上的行为不同。

但有一点,在这两种情况下都有一行Java代码:

socket.setSoTimeout(0)

场景#1(Windows):

  • ssh命令发送到服务器iptables -A OUTPUT --dport XYZ -j DROP
  • 大约60秒后我的控制台说java.net.SocketTimeoutException: Read timed out
  • 连接丢失

场景#2(Centos)

  • 发送与上述相同的命令
  • 我尝试等待多达10分钟,但控制台从不输出异常。

那么,问题,是否有办法使套接字的行为相同(或大致相同)?

我读到Windows实际上不使用SO_TIMEOUT而是使用SO_RCVTIMEO

2 个答案:

答案 0 :(得分:1)

来自setSoTimeout(int timeout)

  

使用指定的超时启用/禁用SO_TIMEOUT,以毫秒为单位。如果将此选项设置为非零超时,则与此Socket关联的InputStream上的read()调用将仅阻止这段时间。如果超时到期,则引发java.net.SocketTimeoutException,尽管Socket仍然有效。必须在进入阻止操作之前启用该选项才能生效。超时必须> 0. 超时为零被解释为无限超时

您是否可以设置实际的超时值?

答案 1 :(得分:0)

在阅读David的回答后,我观察了该套接字的行为,以了解它是如何工作的。

正如David所说,SO_TIMEOUT仅适用于未来的read()次呼叫,而不适用于已经呼叫的呼叫。

我测试的常见模式是:

  • 连接用户(套接字)
  • 交换一些数据
  • 服务器暂时不与用户通信
  • 此时客户端已输入read方法。此时设置SO_TIMEOUT是没用的。
  • 在本地端口上阻止服务器的OUTBOUND流量(一些随机55000+端口)
  • 等待SocketTimeoutException

如果我要在之前设置SO_TIMEOUT ,我的套接字会抛出疯狂的异常。所以,我希望并且在网络中断的情况下抛出异常时会出错。相反,如果流量中断,则会抛出异常。

这可能是Keep-Alive的问题吗?我的套接字将其设置为true

解决方案(经验):

我测量(在Windows上)套接字关闭需要大约60秒。

因此,当我需要切断连接时,我会创建一个线程,如果当前时间距(creation time + 60s)更大,则每2秒检查一次。当它到达那个时间时,它会调用socket.close,这会有效地导致SocketException

这个解决方案绝不是最佳解决方案,但必须这样做,至少目前是这样。

希望这对其他人有任何帮助..