当连接到具有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)
Run Code Online (Sandbox Code Playgroud)
我检查了文档但是因为SocketTimeoutException它写了"表示在套接字读取或接受时发生了超时",但这不是我的情况.因为我在连接建立期间得到它.
这两个例外有什么区别?实际上我期待得到ConnectException任何连接问题(防火墙,端口关闭等)
也来到这里寻找相同的答案,似乎文档很容易被误解:
将此套接字连接到具有指定超时值的服务器。零超时被解释为无限超时。然后连接将阻塞,直到建立或发生错误。
我在这方面忽略的关键部分是“错误”......转到源代码我可以看到 Javaconnect()是如何实际调用 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
}
Run Code Online (Sandbox Code Playgroud)
即我认为SocketTimeoutException是在网络缓慢或主机根本没有响应时被抛出。检查man connect,我可以看到ECCONNREFUSED必须在“无人侦听远程地址”时抛出,即 ICMP 告诉我们。
这意味着,如果像我一样,您尝试使用timeout连接到尚未准备好连接的(本地主机)套接字,那么您就是 SOL'd。
ConnectException 在数据包过滤器/防火墙等上抛出。
当您在套接字上设置了特定的超时,并且在超时之前它没有收到任何内容时,会抛出 SocketTimeoutException 。
示例ServerSocket:
ServerSocket serverSocket = new ServerSocket... // Create server socket
serverSocket.setSoTimeout(1000);
serverSocket.accept();
Run Code Online (Sandbox Code Playgroud)
如果ServerSocket在 1000 毫秒内没有收到任何内容,它将抛出一个SocketTimeoutException. 请注意,所有使用超时的套接字都会引发此异常,而不仅仅是ServerSocket. 这意味着Socket抛出 a 的对象SocketTimeoutException在超时之前没有从被调用的服务器返回任何内容。
要解决此问题,您可以确保服务器响应更快,或设置更高的超时值。