My issue is fairly straightforward. My program requires immediate notification if a network connection is lost. I'm using Java 5, so I'm unable to use the very handy features of NetworkInterface.
Currently I have two different methods of checking for a network connection:
(try..catches removed)
Method One:
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;
Method 2:
Socket socket = new Socket("www.google.com", 80);
netAccess = socket.isConnected();
socket.close();
return netAccess;
However, both of these methods block until a Timeout is reached before returning false. I need a method that will return immediately, but is compatible with Java 5.
Thanks!
EDIT: I forgot to mention that my program is reliant on IP addresses, not DNS names. So checking for an error when resolving a host is out...
2nd EDIT:
Figured out a final solution using NetworkInterface:
Enumeration<NetworkInterface> eni = NetworkInterface.getNetworkInterfaces();
while(eni.hasMoreElements()) {
Enumeration<InetAddress> eia = eni.nextElement().getInetAddresses();
while(eia.hasMoreElements()) {
InetAddress ia = eia.nextElement();
if (!ia.isAnyLocalAddress() && !ia.isLoopbackAddress() && !ia.isSiteLocalAddress()) {
if (!ia.getHostName().equals(ia.getHostAddress()))
return true;
}
}
}
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..
来源:https://stackoverflow.com/questions/6999306/java-quickly-check-for-network-connection