繁体   English   中英

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

[英]What's the connection timeout of a socket created with a connecting constructor?

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

在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)

也许构造函数docs中关于createSocketImpl东西暗示了关于超时的东西,或者其他地方的一些文档说的呢?

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


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

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

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

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

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

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

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

根据消息来源(我在这里看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已经说明的那样)。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM