views:

2079

answers:

7

I want to see if anyone has an easy way of detecting if there is an internet connection when using Java. The current app used the "InternetGetConnectedState" method in the WinInit DLL for windows, but my app needs to be cross-platform for mac operation and this way will not work. I do not know JNI at all either to use DLLs in Java and it became frustrating fast.

Only ways I could think of were tring to open a URL connection to a website and if that fails, return false. My other way is below, but I didn't know if this was generally stable. If I unplug my network cable i do get an UnknownHostException when trying to create the InetAddress. Otherwise if the cable is connected I get a valid InetAddress object. I didnt test the below code on a mac yet.

Thanks for any examples or advice you can provide.

UPDATE: Final code block is at the bottom. I decided to take the advice of an HTTP request (in this case Google). Its simple and sends a request to the site for data to be returned. If I cannot get any content from the connection, there is no internet.

public static boolean isInternetReachable()
     {
      try {

       InetAddress address = InetAddress.getByName("java.sun.com");

       if(address == null)
       {
        return false;
       }

      } catch (UnknownHostException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
       return false;
      }
      catch (IOException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
       return false;
      }
      return true;
     }

Final Code Block:

//checks for connection to the internet through dummy request
     public static boolean isInternetReachable()
     {
      try {
       //make a URL to a known source
       URL url = new URL("http://www.google.com");

       //open a connection to that source
       HttpURLConnection urlConnect = (HttpURLConnection)url.openConnection();

       //trying to retrieve data from the source. If there
       //is no connection, this line will fail
       Object objData = urlConnect.getContent();

      } catch (UnknownHostException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
       return false;
      }
      catch (IOException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
       return false;
      }
      return true;
     }
+4  A: 

That's a perfectly reasonable approach to solving the problem. The bad thing is that you are really testing DNS rather than testing the whole network, but in practice you can often get by with treating those as equivalent.

The other thing to remember, is that you will need to set a system property to turn off dns caching in the java runtime. Otherwise it may continue to report that the network is up based upon cached data (even though it is down).

Another approach would be to actually open an HTTP request to some network address such as this every so often.

jsight
Thanks for the comment. It's always good to get feedback and different ideas. I had a thought of the URL connection, or using HttpURLConnection for that matter. I wasn't aware this tested only DNS but i may have to live with this method.
See final code block above and update note.
+1  A: 

Note that it could return false if the java.sun.com is not responding! In this case you should check another site to be certain.

jeshan
Good point.I think thats why the .NET version of this app used the DLL for the OS. This way the OS knew instantly if there was a connection or not, not pinging of websites or checking steams. It would pose the question when to draw the line. After one site? Two? Exactly why i wanted input.
A: 

Haven't tested this, but I suggest looking at java.net.NetworkInterface.getNetworkInterfaces(). This returns an Enumeration of all network interfaces on the machine, or null if there are none.

I'm not sure if it's safe to assume that a non-null response ensures a valid network connection -- depending on your needs, you may or may not need to filter out loopback addresses (which I think you could do with java.net.NetworkInterface.getInetAddresses() on each returned NetworkInterface, and then calling InetAddress.isLoopbackAddress() on each one.)

jptsetme
A: 

The only way to be CERTAIN that you can reach a given service, is to do a dummy request to that service. Pings may be blocked by firewalls. Some server may be reachable, others not. If you need to talk to a webservice, have a static page to return for these requests.

Also, remember to ask the user before trying to reach out.

Thorbjørn Ravn Andersen
A: 

The question doesn't really have a meaning. There is no such thing as a 'connection to the Internet'. You have to try to create one. The Windows API referred to only tells you whether your modem is dialled in or not, and I've seen it actually cause dial-ins, which is not exactly the idea. Not that I've had a dial-in for the last 8 years or so.

EJP
A: 

A problem with the first solution is that InetAddress has a cache, so, when you lose the connection for the next few invocation the name is resolved via the java cache. With the URL connection aproach you have the problem that you use getContent that should fetch html so there you have data consumption. If the invocations are done very often that could be a problem (more so if you dont have an unlimited data plan on the device running the software).

I think the best solution would be to do a TCP connection to the 80 port an close it inmediatly after a successfull connection. That would behave as the final code but would have much less traffic.

andsegu
A: 

I must add that although the final code block given above is good, it has one flaw - it is possible for it to take a very long time to contact the address specified, but the address is still reachable.

In my instance when testing with one address the method would return true, but take 10 seconds or longer to get a response. In this case the server was reachable, but not for any useful purposes since the connection was so slow. This occurs because the default timeout for HttpURLConnection is 0, or infinite.

For this reason I'd recommend you do the checking off the UI thread, and add urlConnect.setConnectTimeout(1000); before calling urlConnect.getContent();

This way you know the address is reachable, and that it won't take 5 years to download a 10k file.

(You might of course want to change the the timeout time to suit your needs)

Also I'd recommend not checking a generic address (google.com etc) unless your program generally accesses more than a few domains. If you're just accessing one or two then check that domain.

Joseph Earl