在指定超时前抛出异常 "java.net.ConnectException: Connection timed out: connect"

Exception "java.net.ConnectException: Connection timed out: connect" is thrown before specified timeout

我有以下代码:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;

public class ScoketTimeoutMain
{
    public static void main( String[] args )
    {

        Socket socket = new Socket();
        InetSocketAddress address = new InetSocketAddress( "example.com", 81 );
        final long l = System.currentTimeMillis();
        try
        {
            socket.connect( address, 60000 );
        }
        catch( IOException aE )
        {
            aE.printStackTrace();
            System.out.println( System.currentTimeMillis() - l );
        }
    }
}

大约 21 秒后出现连接超时:

java.net.ConnectException: Connection timed out: connect
    at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
    at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at com.kulig.ScoketTimeoutMain.main(ScoketTimeoutMain.java:17)
21004

我不明白为什么在 21 秒而不是 60 秒后抛出异常。

===编辑===

如果我将超时设置为小于 21 秒,则它可以正常工作。 例如:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;

public class ScoketTimeoutMain
{
    public static void main( String[] args )
    {

        Socket socket = new Socket();
        InetSocketAddress address = new InetSocketAddress( "example.com", 81 );
        final long l = System.currentTimeMillis();
        try
        {
            socket.connect( address, 2000 );
        }
        catch( IOException aE )
        {
            aE.printStackTrace();
            System.out.println( System.currentTimeMillis() - l );
        }
    }
}

java.net.SocketTimeoutException: connect timed out
    at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
    at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at com.kulig.ScoketTimeoutMain.main(ScoketTimeoutMain.java:17)
2002

所以又发生了一些超时。我不知道是什么原因造成的,也不知道如何设置其他超时。

我得到了完全相同的 21 秒 (21007)。在互联网上搜索,21 秒超时并不少见。基于这个hotfix,我更改了TCP的Max SYN Retransmissions参数,得到了60秒超时:

netsh interface tcp set global MaxSynRetransmissions=5

默认值为2