I’m trying to connect to a remote host trying over and over waiting for it to come up. However, after one shot with a Connection Refused exception (because the server isn’t running yet), it throws Socket closed exception continuously. Why would the socket be closed? The socket should simply be in the same state as it was before the failed connect() call, shouldn’t it?
while(!tcpSock.isConnected()) { try { tcpSock.connect(destination); } catch (SocketException e) { System.err.println(e.toString()); } }
results in
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
Desired behavior is
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
(Once I’m done debugging, I’ll comment out the print of the exception.)
Advertisement
Answer
Looking at the OpenJDK source code … when the connect(...)
call fails, the SocketImpl
code calls close()
on the Socket
.
This is the code in Java 11 (in 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 */ } } } }
That close()
call on the SocketImpl
object leads to the Socket
being marked as closed.
In short, a Java Socket
object does not support retrying after a failed connection attempt. If you want to retry, your code needs to create a new Socket
object.
Discussion of whether it is correct for Socket
to behave this way is beside the point. It just does … and it is highly unlikely that this will ever change. The only thing that might change is that they might document this behavior in the Socket
javadocs.