28

When I'm using e.g. PuTTY and my connection gets lost (or when I do a manual ipconfig /release on Windows), it responds directly and notifies my connection was lost.

I want to create a Java program which monitors my Internet connection (to some reliable server), to log the date/times when my internet fails.

I tried use the Socket.isConnected() method but that will just forever return "true". How can I do this in Java?

kresjer
  • 767
  • 3
  • 10
  • 17

9 Answers9

22

Well, the best way to tell if your connection is interrupted is to try to read/write from the socket. If the operation fails, then you have lost your connection sometime.

So, all you need to do is to try reading at some interval, and if the read fails try reconnecting.

The important events for you will be when a read fails - you lost connection, and when a new socket is connected - you regained connection.

That way you can keep track of up time and down time.

jjnguy
  • 136,852
  • 53
  • 295
  • 323
  • 2
    Not correct. If you've set a read timeout and it triggers you get an exception, i.e. the operation fails, but it doesn't necessarily indicate a lost connection. – user207421 Jul 26 '13 at 19:10
  • 3
    @EJP It's not always correct, but it will give you a good idea about what's going on. – jjnguy Jul 26 '13 at 19:51
  • 12
    No it won't. You can't distinguish between a slow server and a lost connection with a read timeout. – user207421 Aug 16 '13 at 22:15
14

Even though TCP/IP is "connection oriented" protocol, normally no data is sent over an idle connection. You can have a socket open for a year without a single bit sent over it by the IP stack. In order to notice that a connection is lost, you have to send some data on the application level.(*) You can try this out by unplugging the phone cable from your ADSL modem. All connections in your PC should stay up, unless the applications have some kind of application level keepalive mechanism.

So the only way to notice lost connection is to open TCP connection to some server and read some data from it. Maybe the most simple way could be to connect to some FTP server and fetch a small file - or directory listing - once in a while. I have never seen a generic server which was really meant to be used for this case, and owners of the FTP server may not like clients doing this.

(*) There is also a mechanism called TCP keepalive but in many OS's you have to activate it for all applications, and it is not really practical to use if you want to notice loss of connection quickly

tputkonen
  • 5,579
  • 16
  • 60
  • 88
8

If the client disconnects properly, a read() will return -1, readLine() returns null, readXXX() for any other X throws EOFException. The only reliable way to detect a lost TCP connection is to write to it. Eventually this will throw an IOException 'connection reset', but it takes at least two writes due to buffering.

user207421
  • 305,947
  • 44
  • 307
  • 483
7

Why not use the isReachable() method of the java.net.InetAddress class?

How this works is JVM implementation specific but:

A typical implementation will use ICMP ECHO REQUESTs if the privilege can be obtained, otherwise it will try to establish a TCP connection on port 7 (Echo) of the destination host.

If you want to keep a connection open continually so you can see when that fails you could connect to server running the ECHO protocol yourself rather than having isReachable() do it for you and read and write data and wait for it to fail.

David Webb
  • 190,537
  • 57
  • 313
  • 299
  • 1
    Hmm maybe I wasn't clear in my question. What sometimes happens at my systen is that my internet drops for a few seconds and all connections get closed. A second later everything is fine. I want to monitor this on a daily basis, to make reports how often this is happening. – kresjer Jun 09 '09 at 12:56
  • You could connect to an ECHO server yourself and keep sending and reading data; added this to the answer. – David Webb Jun 09 '09 at 13:36
  • 2
    Whether an existing connection is still open has nothing to do with `isReachable()` whatsoever. – user207421 Nov 20 '15 at 09:47
1

You might want to try looking at the socket timeout interval. With a short timeout (I believe the default is 'infinite timeout') then you might be able to trap an exception or something when the host becomes unreachable.

poundifdef
  • 18,726
  • 23
  • 95
  • 134
1

Okay so I finally got it working with

try
{
    Socket s = new Socket("stackoverflow.com",80);
    DataOutputStream os = new DataOutputStream(s.getOutputStream());
    DataInputStream is = new DataInputStream(s.getInputStream());
    while (true)
    {
        os.writeBytes("GET /index.html HTTP/1.0\n\n");
        is.available();
        Thread.sleep(1000);
    }
}
catch (IOException e)
{
    System.out.println("connection probably lost");
    e.printStackTrace();
}

Not as clean as I hoped but it's not working if I leave out the os.writeBytes().

kresjer
  • 767
  • 3
  • 10
  • 17
  • 19
    This is something that you definitely should not use. It can almost be considered as a DOS attack against stackoverflow.com! – tputkonen Jun 09 '09 at 19:16
  • A more friendly way to do this would be to host a simple page/script on a web host that (likely) would not mind a constant load like this, especially if the rendered page was small (just a simple "h" would do). This should provide a small foot print and if the calls are made every second or so the server would likely not bog down resulting in a DOS. In theory anyway. – Kingsolmn Mar 03 '13 at 16:17
  • 4
    This is nonsense. Calling available() is usually pointless, and calling it and throwing away the result definitely so. The sleep is literally a waste of time. This technique accomplishes precisely nothing. – user207421 Jul 26 '13 at 19:11
0

The isConnected()method inside Socket.java class is a little misleading. It does not tell you if the socket is currently connected to a remote host (like if it is unclosed). Instead, it tells you whether the socket has ever been connected to a remote host. If the socket was able to connect to the remote host at all, this method returns true, even after that socket has been closed. To tell if a socket is currently open, you need to check that isConnected() returns true and isClosed() returns false. For example:

boolean connected = socket.isConnected() && !socket.isClosed();
Alboz
  • 1,833
  • 20
  • 29
  • 1
    _To tell if a socket is currently open, you need to check that isConnected() returns true and isClosed() returns false_ This does not appear to be true. See: [https://stackoverflow.com/questions/44685374/why-am-i-sending-an-rst-if-my-socket-is-connected-and-not-closed] (link) – user316117 Jun 22 '17 at 16:08
  • @user316117 that question is not clear but if the isClosed is FALSE and the isConnected is TRUE it means that you managed to connect and the connection was never closed. If you think you're disconnected and the "isClosed()" returns FALSE then you have discovered a JDK bug. See this documentation: https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html#isConnected-- – Alboz Jun 24 '17 at 09:23
  • 1
    @Alboz It means you managed to connect and the *socket* hasn't been closed yet. It has nothing to do with the connection, as you stated yourself in your own answer. There is no JDK bug unless you closed your own socket and then got `isClosed() == false`. – user207421 Jul 16 '17 at 13:46
  • @Alboz if the socket is disconnected from the other point, isClosed() still will be false and isConnected will be true. I think the best way to check it is trying to write to the pipe, thats what im doing. – justcode Apr 24 '18 at 12:14
0

You could ping a machine every number of seconds, and this would be pretty accurate. Be careful that you don't DOS it.

Another alternative would be run a small server on a remote machine and keep a connection to it.

Geo
  • 93,257
  • 117
  • 344
  • 520
  • How would you know when you became disconnected to the small server? And a **major** use of Java is in Android mobile devices where constant pinging and keepalives are a Bad Idea because they kill the battery. – user316117 Jun 22 '17 at 16:10
0

Its probably simpler to connect to yahoo/google or somewhere like this.

    URL yahoo = new URL("http://www.yahoo.com/");
    URLConnection yc = yahoo.openConnection();
    int dataLen = yc.getContentLength() ;

Neil

Neil Wightman
  • 1,103
  • 2
  • 9
  • 29
  • Nothing to do with whether an existing connection is still open whatsoever. – user207421 Nov 20 '15 at 09:57
  • Question was how to write a "Java program which monitors my internet connection" which this will do fine. Java directly cannot monitor if putty connection is lost but will say when a generic network issue occurs. You could call "netstat" from java to monitor a network connection from another process. – Neil Wightman Nov 30 '15 at 10:04
  • Windows programmers using WinSock can register for an event. This fires even after a cable has been disconnected. (with a few seconds delay) [https://stackoverflow.com/questions/44681648/in-android-how-can-i-receive-an-event-when-my-socket-closes-or-disconnects](link) – user316117 Jun 22 '17 at 16:13