当连接到具有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
(防火墙,端口关闭等)
答案 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
。