在实践项目中,经常要处理网络异常等问题。为此,专门设计一个类,随时可以使用。
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.Enumeration;
/**
* @author administrator
*
*/
public class NetworkMonitor implements Runnable {
private String m_strUrl = "192.168.1.27";
private static boolean m_bNetworkAvailable = false;
/**
*
*/
public NetworkMonitor() {
// TODO:
}
/**
* @param strUrl
*/
public NetworkMonitor(String strUrl) {
this.m_strUrl = strUrl;
}
/**
* @return
*/
public static boolean isNetworkAvailable() {
return m_bNetworkAvailable;
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
while (true) {
try {
InetAddress inetAddress = InetAddress.getByName(m_strUrl);
m_bNetworkAvailable = inetAddress.isReachable(5000); //测试是否可以达到该地址
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
m_bNetworkAvailable = false;
} catch(UnknownHostException e) {
// System.err.println("连接失败");
m_bNetworkAvailable = false;
} catch (IOException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
m_bNetworkAvailable = false;
}
}
}
public void isAddressAvailable(String ip) {
try {
InetAddress address = InetAddress.getByName(ip); //ping this IP
if (address instanceof java.net.Inet4Address) {
System.out.println(ip + " is ipv4 address");
} else if (address instanceof java.net.Inet6Address) {
System.out.println(ip + " is ipv6 address");
} else {
System.out.println(ip + " is unrecongized");
}
if (address.isReachable(5000)) {
System.out.println("SUCCESS - ping " + ip + " with no interface specified");
} else {
System.out.println("FAILURE - ping " + ip + " with no interface specified");
}
System.out.println("\n-------Trying different interfaces--------");
Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
while (netInterfaces.hasMoreElements()) {
NetworkInterface ni = netInterfaces.nextElement();
System.out.println( "Checking interface, DisplayName:" + ni.getDisplayName() + ", Name:" + ni.getName());
if(address.isReachable(ni, 0, 5000)){
System.out.println("SUCCESS - ping " + ip);
} else {
System.out.println("FAILURE - ping " + ip);
}
Enumeration<InetAddress> ips = ni.getInetAddresses();
while(ips.hasMoreElements()) {
System.out.println("IP: " + ips.nextElement().getHostAddress());
}
System.out.println("-------------------------------------------"); }
} catch (Exception e) {
System.out.println("error occurs.");
e.printStackTrace();
}
}
}
实际中需要知道网络状态的时候,不必专门去再检查,因为那样可能会阻塞,导致调用者挂起,在这里直接调用isNetworkAvailable方法可以立即知道网络状态,所以性能不会受到任何影响。
这个类下面实现的线程run方法中,检查网络也是2秒钟检查一次,不会影响整个程序的性能,如果有更高的要求,可以改成1秒或者0.5秒,我的意见是2秒够了。因为网络断开很快,但是要恢复也是需要点时间的,所以不必反复检查,那样会影响性能。
调用示例:
public class Startup {
/**
* @see 应用程序入口
* @param args
*/
public static void main(String[] args) {
Startup startup = new Startup();
startup.startNetworkMonitor();
for (int i = 0; i < 60; i++) {
System.out.println("network[" + i + 1 +"]: " + NetworkMonitor.isNetworkAvailable());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void startNetworkMonitor() {
NetworkMonitor networkMonitor = new NetworkMonitor();
networkMonitor.isAddressAvailable("192.168.1.1");
Thread thread = new Thread(networkMonitor);
thread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
试运行就可以知道, 这一句
System.out.println("network[" + i + 1 +"]: " + NetworkMonitor.isNetworkAvailable());
完全就是毫秒级返回,各方面表现非常理想。