4

使用连接构造函数创建的套接字的连接超时是多少?

在 Java SE 6 中,以下 Socket 构造函数将立即连接套接字,而不必在构造后对其调用 connect:

  • Socket(InetAddress address, int port)
  • Socket(InetAddress host, int port, boolean stream)
  • Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
  • Socket(String host, int port)
  • Socket(String host, int port, boolean stream)
  • Socket(String host, int port, InetAddress localAddr, int localPort)

尽管 Java SE 人员创建了 500 种构造套接字的方法既方便又好用,因此您只需浏览 500 种方法即可找到符合您要求的方法(而不是调用new Socket()后跟Socket#connect()),但没有一个这些构造函数的文档说明了连接超时是什么或它们是否/如何调用connect(SocketAddress endpoint, int timeout)

也许构造函数文档中谈论的内容createSocketImpl暗示了超时,或者其他地方的一些文档说了什么?

任何人都知道这些构造函数的实际连接超时是多少?


背景:好的,假设规范确实模棱两可(我认为 Java 是可移植的?),我试图弄清楚为什么客户的代码在看似随机的时间冻结。我有一些代码调用了一些调用这些构造函数之一的开源库。我想知道调用这些构造函数之一是否会使超时无限或很长。我不知道客户使用的是什么版本的 JDK,所以如果规范在某处说超时,那就太好了。我想我可能可以从我的客户那里获得 JDK 版本,但它可能是闭源 JDK。在那种情况下,我可以对他们版本的 SE 库中的代码进行逆向工程以找出答案吗?难吗?我会进监狱吗?

4

6 回答 6

3

Java 规范是假的。它没有说明任何这些构造函数的超时时间,因此实现可以将超时设置为 0.000000000001 纳秒并且仍然是正确的。此外:非有限超时甚至不受 vm 实现的尊重(如此处所示),因此看起来规范甚至无关紧要,因为没有人遵循它。

结论:您必须阅读客户 JVM 的封闭源代码二进制文件(可能是非法的,但您必须做您必须做的事情),还有 OS 套接字文档。

于 2012-10-19T16:28:28.207 回答
3

尽管 Java 文档说超时是无限的,但这实际上意味着 JVM 不会对连接操作施加任何超时,但是操作系统可以自由地对任何套接字操作施加超时设置。

因此,实际超时将取决于您的操作系统的 TCP/IP 层设置。

一个好的编程习惯是为所有套接字操作设置超时,最好通过配置文件进行配置。使其可配置的优势在于,根据部署环境的网络负载,可以调整超时,而无需重新构建/重新测试/重新发布整个软件。

于 2012-10-19T15:37:03.563 回答
2

根据消息来源(我在这里查看 1.5_13,但应该没有区别),不同的 Socket 构造函数都调用Socket(SocketAddress, SocketAddress, boolean),定义为:

private Socket(SocketAddress address, SocketAddress localAddr,
           boolean stream) throws IOException {
    setImpl();

    // backward compatibility
    if (address == null)
        throw new NullPointerException();

    try {
        createImpl(stream);
        if (localAddr == null)
        localAddr = new InetSocketAddress(0);
        bind(localAddr);
        if (address != null)
        connect(address);
    } catch (IOException e) {
        close();
        throw e;
    }
}

connect(SocketAddress)定义为

public void connect(SocketAddress endpoint) throws IOException {
    connect(endpoint, 0);
}

因此,无限超时(正如@Keppil 已经说过的那样)。

于 2012-10-19T15:00:43.313 回答
2

查看code of Socket in OpenJDK 6-b14,可以看到这些构造函数调用connect(socketAddress, 0),这意味着一个无限的超时值。

于 2012-10-19T14:52:50.760 回答
1

它取决于平台,但大约需要一分钟。connect() 的 Javadoc 声明它是无限的是不正确的。另请注意,connect() 超时参数只能用于减少默认值,而不能增加它。

于 2012-10-19T20:58:45.100 回答
1

Socket 类从 Java 1.0 开始就存在,但当时只能创建套接字,这些套接字会立即连接,并且无法指定连接超时。从 Java 1.4 开始,可以创建未连接的套接字,然后使用 connect 方法指定超时。我假设有人只是忘记澄清“旧”构造函数的文档,指定它们仍然在没有明确超时的情况下运行。

带有超时参数的连接方法的文档显示“超时为零被解释为无限超时”。这实际上也是不正确的,因为它只意味着 Java VM 没有暗示超时。即使超时为 0,连接操作仍可能在操作系统的 TCP/IP 堆栈中超时。

于 2012-10-19T15:44:41.217 回答