It is interesting. I have tested and can reproduce the behavior you described.
Firstly, the highest voted answer gives a good discussion of the Java Socket API:
Java socket API: how do I know if a connection is closed?
From this, I wondered if trying to read a byte from a socket would allow us to check if it was really open
// Endpoint that does not exist Socket socket = new Socket("1.2.3.4", 1234); InputStream tmpIn = socket.getInputStream(); int result = tmpIn.read(); Log.i("SocketTest", "read() result: " + result);
In case the endpoint is invalid, I found that the call to read() returns -1 after about 10 seconds.
In the case where there is a listener on the IP and port, the read() call seems to block forever until something happens, for example, actually receiving data from the server or losing the Internet connection, etc.
Based on this difference, I wrapped this test in a new class:
public class VerifiedSocket extends Socket { public VerifiedSocket(String ip, int port, int millisecondTimeout) throws UnknownHostException, IOException{ super(ip,port); ReadThread tryRead = new ReadThread(); tryRead.start(); try { tryRead.join(millisecondTimeout); } catch (InterruptedException e) { } if(tryRead.getReadValue()==-1){
And then test it like this:
try { VerifiedSocket socket = new VerifiedSocket("1.2.3.4", 1234, 20000); Log.i("SocketTest", "Endpoint is valid"); socket.close(); } catch (UnknownHostException e) { Log.e("SocketTest", e.getLocalizedMessage()); } catch (IOException e) { Log.e("SocketTest", e.getLocalizedMessage()); }
If I use an invalid endpoint in Wifi, the VerifiedSocket constructor throws an exception with a timeout. If I use an invalid endpoint for mobile data, it throws an IOException with the message "Endpoint is invalid." Not perfect, but hopefully this can help you.