为什么 'java.net.SocketException: Socket closed' 在 'java.net.ConnectException: Connection refused' 之后?
Why 'java.net.SocketException: Socket closed' after 'java.net.ConnectException: Connection refused'?
我正在尝试连接到远程主机,一遍又一遍地等待它出现。但是,在出现一次拒绝连接异常后(因为服务器还没有运行),它会连续抛出套接字关闭异常。为什么套接字会被关闭?套接字应该简单地处于与失败的 connect() 调用之前相同的状态,不是吗?
while(!tcpSock.isConnected()) {
try {
tcpSock.connect(destination);
} catch (SocketException e) {
System.err.println(e.toString());
}
}
结果
Setting TCP client mode connecting to remote host localhost/127.0.0.1 port 4500
java.net.ConnectException: Connection refused: connect
java.net.SocketException: Socket closed
java.net.SocketException: Socket closed
java.net.SocketException: Socket closed
java.net.SocketException: Socket closed
期望的行为是
Setting TCP client mode connecting to remote host localhost/127.0.0.1 port 4500
java.net.ConnectException: Connection refused: connect
java.net.ConnectException: Connection refused: connect
java.net.ConnectException: Connection refused: connect
java.net.ConnectException: Connection refused: connect
Established connection to: localhost port 4500
(一旦我完成调试,我将注释掉异常的打印。)
查看 OpenJDK 源代码...当 connect(...)
调用失败时,SocketImpl
代码在 Socket
上调用 close()
。
这是Java11(java.net.AbstractPlainSocketImpl
)中的代码:
protected void connect(String host, int port)
throws UnknownHostException, IOException
{
boolean connected = false;
try {
InetAddress address = InetAddress.getByName(host);
this.port = port;
this.address = address;
connectToAddress(address, port, timeout);
connected = true;
} finally {
if (!connected) {
try {
close(); // <<---- HERE
} catch (IOException ioe) {
/* Do nothing. If connect threw an exception then
it will be passed up the call stack */
}
}
}
}
对 SocketImpl
对象的 close()
调用导致 Socket
被标记为已关闭。
简而言之,Java Socket
对象不支持在连接尝试失败后重试。如果您想重试,您的代码需要创建一个新的 Socket
对象。
关于 Socket
这样的行为是否 正确 的讨论是离题的。确实如此……而且这种情况极不可能改变。唯一可能改变的是他们 可能 在 Socket
javadocs 中记录此行为。
我正在尝试连接到远程主机,一遍又一遍地等待它出现。但是,在出现一次拒绝连接异常后(因为服务器还没有运行),它会连续抛出套接字关闭异常。为什么套接字会被关闭?套接字应该简单地处于与失败的 connect() 调用之前相同的状态,不是吗?
while(!tcpSock.isConnected()) {
try {
tcpSock.connect(destination);
} catch (SocketException e) {
System.err.println(e.toString());
}
}
结果
Setting TCP client mode connecting to remote host localhost/127.0.0.1 port 4500
java.net.ConnectException: Connection refused: connect
java.net.SocketException: Socket closed
java.net.SocketException: Socket closed
java.net.SocketException: Socket closed
java.net.SocketException: Socket closed
期望的行为是
Setting TCP client mode connecting to remote host localhost/127.0.0.1 port 4500
java.net.ConnectException: Connection refused: connect
java.net.ConnectException: Connection refused: connect
java.net.ConnectException: Connection refused: connect
java.net.ConnectException: Connection refused: connect
Established connection to: localhost port 4500
(一旦我完成调试,我将注释掉异常的打印。)
查看 OpenJDK 源代码...当 connect(...)
调用失败时,SocketImpl
代码在 Socket
上调用 close()
。
这是Java11(java.net.AbstractPlainSocketImpl
)中的代码:
protected void connect(String host, int port)
throws UnknownHostException, IOException
{
boolean connected = false;
try {
InetAddress address = InetAddress.getByName(host);
this.port = port;
this.address = address;
connectToAddress(address, port, timeout);
connected = true;
} finally {
if (!connected) {
try {
close(); // <<---- HERE
} catch (IOException ioe) {
/* Do nothing. If connect threw an exception then
it will be passed up the call stack */
}
}
}
}
对 SocketImpl
对象的 close()
调用导致 Socket
被标记为已关闭。
简而言之,Java Socket
对象不支持在连接尝试失败后重试。如果您想重试,您的代码需要创建一个新的 Socket
对象。
关于 Socket
这样的行为是否 正确 的讨论是离题的。确实如此……而且这种情况极不可能改变。唯一可能改变的是他们 可能 在 Socket
javadocs 中记录此行为。