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

时间:2012-10-19 14:40:50

标签: java sockets ambiguity

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

在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列表即可找到您想要的那种(而不是调用{{1} }后跟new Socket()),这些构造函数的所有文档都没有说明连接超时是什么,或者是否/如何调用Socket#connect()

也许构造函数文档中讨论connect(SocketAddress endpoint, int timeout)的内容暗示了超时的某些内容,或者其他地方的某些文档说的是什么?

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


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

6 个答案:

答案 0 :(得分:3)

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

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

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

答案 1 :(得分:3)

Java规范是假的。它没有说明任何构造函数的超时是什么,因此实现可以将超时设置为0.000000000001纳秒并且仍然是正确的。 Furthurmore:非有限超时甚至不受vm实现的尊重(如此处所示)所以看起来像spec甚至不重要因为没有人跟着它。

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

答案 2 :(得分:2)

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

答案 3 :(得分: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已经说过的那样)。

答案 4 :(得分:1)

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

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

答案 5 :(得分:1)

它依赖于平台但是大约一分钟。 connect()的Javadoc声明它是无限的是不正确的。另请注意,connect()timeout参数只能用于降低默认值,而不能增加默认值。