java.net.SocketTimeoutException vs java.net.ConnectException

时间:2014-06-09 08:43:50

标签: java sockets

当连接到具有Java客户端套接字的服务器时,我有两个不同的连接超时异常。

Caused by: java.net.SocketTimeoutException: connect timed out
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:381) 

Caused by: java.net.ConnectException: Connection refused: connect 
    at java.net.PlainSocketImpl.socketConnect(Native Method) 
    at java.net.PlainSocketImpl.doConnect(Unknown Source) 

我检查了文档,但对于SocketTimeoutException,它写了“表示在套接字读取或接受时发生了超时”,但这不是我的情况。因为我在连接建立期间得到它。

这两个例外有什么区别?实际上我期待在任何连接问题中获得ConnectException(防火墙,端口关闭等)

4 个答案:

答案 0 :(得分:3)

同样来到这里寻找相同的答案,似乎the docs很容易被误解:

  

使用指定的超时值将此套接字连接到服务器。一个   超时为零被解释为无限超时。连接   然后将阻止直到建立或发生错误。

我忽略的关键部分是“错误”......转到the source我可以看到Java的connect()实际上是如何调用Linux connect()的:

if (timeout <= 0) {
    connect = connect(args...);
    if (connect == -1 && errno == EINPROGRESS) {
        connect = poll(args...);
        // try again on EINTR
    }
} else {
    // Go to non-blocking mode for a timeout.
    connect = connect(args...);

    if (connect!=0) {
        // not EINPROGRESS? -> throw ConnectException
        while (!connect || !error || timedout) {
            connect = poll(args...);
            // error / timedout handling
        }
        if (timedout) {
            // throw SocketTimeoutException
        }
    }
}

/* report the appropriate exception */
if (error) {
    //EINVAL; throw SocketException
    //EINTR; throw InterruptedIOException
    //EPROTO; throw ProtocolException
    //ECONNREFUSED;ETIMEDOUT; throw ConnectException
    //EHOSTUNREACH; throw NoRouteToHostException
    //EADDRNOTAVAIL; throw NoRouteToHostException
    //EISCONN, EBADF, other; throw SocketException
}

即。我认为当网络速度缓慢或主机根本没有响应时,会抛出SocketTimeoutException。检查man connect,我可以看到,当“没人监听远程地址”时,必须抛出ECCONNREFUSED,即ICMP告诉我们。

这意味着如果像我一样,你试图使用timeout连接到一个尚未准备好连接的(localhost)套接字,那么你就是SOL'd。

答案 1 :(得分:0)

在包过滤器/防火墙等上抛出ConnectException。

如果在套接字上设置了特定的超时,并且在超时之前没有收到任何内容,则抛出SocketTimeoutException。

ServerSocket的示例:

ServerSocket serverSocket = new ServerSocket... // Create server socket
serverSocket.setSoTimeout(1000);  
serverSocket.accept();

如果ServerSocket在1000毫秒内没有收到任何内容,则会抛出SocketTimeoutException。请注意,对于使用超时的所有套接字,不仅仅ServerSocket抛出此异常。这意味着抛出Socket的{​​{1}}对象在超时之前没有从被叫服务器返回任何内容。

要解决此问题,您可以确保服务器响应更快,或设置更高的超时值。

答案 2 :(得分:0)

如果您在SocketTimeoutException上指定了超时,或者您在connect(),setSoTimeout()和{Socket上拨打了ServerSocket,则会收到read()分别为{1}}或accept()次。在connect(),的情况下,这是一个严重的问题:您尝试连接的内容不存在或位于防火墙后面,您无法分辨哪个。

如果对等方主动拒绝您的连接请求,您将获得connection refused,这通常意味着您指定的端口没有任何内容侦听。请注意,与超时不同,这意味着收到 的响应,并且它是否定的。

答案 3 :(得分:-1)

Caused by: java.net.SocketTimeoutException: connect timed out

由于对等方不可用而无法连接。 你的第二个问题,阅读怎么样?比你得到

 Caused by: java.net.SocketTimeoutException: Read timed out

如果对等方处于活动状态但拒绝连接,则第三种可能性connection refused