Java Quickly check for network connection

谁说我不能喝 提交于 2019-12-04 02:41:23

From JGuru

Starting with Java 5, there is an isReachable() method in the InetAddress class. You can specify either a timeout or the NetworkInterface to use. For more information on the underlying Internet Control Message Protocol (ICMP) used by ping, see RFC 792 (http://www.faqs.org/rfcs/rfc792.html).

Usage from Java2s

  int timeout = 2000;
  InetAddress[] addresses = InetAddress.getAllByName("www.google.com");
  for (InetAddress address : addresses) {
    if (address.isReachable(timeout))
      System.out.printf("%s is reachable%n", address);
    else
      System.out.printf("%s could not be contacted%n", address);
  }

If you want to avoid blocking use Java NIO (Non-blocking IO) in the java.nio package

String host = ...; 
InetSocketAddress socketAddress = new InetSocketAddress(host, 80); 
channel = SocketChannel.open(); 
channel.configureBlocking(false); 
channel.connect(socketAddress);

You need to first create an interface called NetworkListener, for example

public interface NetworkListener {
    public void sendNetworkStatus(String status);
}

Next, create a class and call it NetworkStatusThread, for example

public class NetworkStatusThread implements Runnable {
    List listenerList = new Vector();

    @SuppressWarnings("unchecked")
    public synchronized void addNetworkListener(NetworkListener nl) {
        listenerList.add(nl);
    }

    public synchronized void removeNetworkListener(NetworkListener nl) {
        listenerList.remove(nl);
    }


    private synchronized void sendNetworkStatus(String status) {
        // send it to subscribers
        @SuppressWarnings("rawtypes")
        ListIterator iterator = listenerList.listIterator();
        while (iterator.hasNext()) {
            NetworkListener rl = (NetworkListener)iterator.next();
            rl.sendNetworkStatus(status);
        }
    }

    public void run() {
        while (true) {
        System.out.println("Getting resource status");
        try {
             Thread.sleep(2000);
             System.out.println("Sending resource status to registered listeners");
             this.sendResourceStatus("OK");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

 }

Then in your class that instantiates the Thread, do this:

NetworkStatusThread netStatus = new NetworkStatusThread();
netStatus.addNetworkListener(this);
Thread t = new Thread(netStatus);
t.Start();

Also, in that class, you need to implement the NetworkListener, in order to get the callbacks.

In your run() method above, you can implement the code by @Ali, but pass my status:

  int timeout = 2000;
  InetAddress[] addresses = InetAddress.getAllByName("www.google.com");
  for (InetAddress address : addresses) {
    if (address.isReachable(timeout))
       this.sendResourceStatus("OK");
    else
       this.sendResourceStatus("BAD");
  }

My program requires immediate notification if a network connection is lost.

Bad luck. You can't get an immediate notification with TCP/IP. It is full of buffering and retries and timeouts, so it doesn't do anything immediately, and TCP by design doesn't have anything corresponding to a 'dial tone', nor any API. The only way to detect a lost connection is to try to do I/O over it.

I'm using Java 5, so I'm unable to use the very handy features of NetworkInterface.

They won't help you either. All they can tell you is whether an NIC is up or down, nothing about the state of your connectedness to the wider world.

URL url = new URL("http://www.google.com");
HttpURLConnection urlConnect = (HttpURLConnection) url.openConnection();
// trying to retrieve data from the source. If offline, this line will fail:
Object objData = urlConnect.getContent();
return true;

That will timeout with a DNS failure if you're offline.

Socket socket = new Socket("www.google.com", 80);
netAccess = socket.isConnected();
socket.close();
return netAccess;

Ditto. However even if it didn't, socket.isConnected() would always return true. Those APIs like isConnected(), isBound(), isClosed(), only tell you what you have done to the socket. They don't tell you anything about the state of the connection. They can't, for the reason I gave above.

And you forgot to close the socket in the case of an exception, so you have a resource leak.

I need a method that will return immediately.

Impossible for the reasons given. You need to redesign around the realization that this function doesn't exist.

Did you try by issuing a DNS resolve?

You can try with:

public static InetAddress[] getAllByName(String host)

but I'm unsure if this will require the timeout too..

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!