2011-08-09 97 views
10

我的问题相当简单。如果网络连接丢失,我的程序需要立即通知。我使用的是Java 5,因此我无法使用NetworkInterface的非常方便的功能。Java快速检查网络连接

目前我有检查的网络连接的两种不同的方法:
(try..catches移除)

方法一:

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; 

方法2:

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

但是,在返回false之前,这两种方法都会阻塞,直到超时。我需要一种立即返回的方法,但与Java 5兼容。

谢谢!

编辑: 我忘了提及我的程序依赖于IP地址,而不是DNS名称。对于错误解析主机出来的时候所以检查...

2日编辑:

想通了使用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; 
       } 
      } 
     } 
+0

我对Java不太熟悉,但我认为方法2中的'http://'太多了。 – glglgl

+0

您可以使用Java 5.0运行可以使用NetworkInterface的Java 6或7应用程序。;) –

+0

好像你需要一个回调方法来在网络状态发生变化时通知你。 – 2011-08-09 16:10:43

回答

10

从JGuru

与开始在Java 5中, InetAddress类中有isReachable()方法。您可以指定超时或要使用的NetworkInterface。有关Ping使用的基本 Internet控制消息协议(ICMP)的更多信息,请参阅RFC 792 (http://www.faqs.org/rfcs/rfc792.html)。从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); 
    } 

用法如果你想避免阻塞在java.nio包采用Java NIO(非阻塞IO)

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

不幸的是,这个方法仍然会阻塞,直到到达timout。更糟糕的是,它会阻塞阵列中的每个InetAddress。不过谢谢。 – BenCole

+0

嗯...你需要的是java.nio ...它的名字是NON-BLOCKING-IO 'String host = ...;InetSocketAddress socketAddress = new InetSocketAddress(host,80); channel = SocketChannel.open(); channel.configureBlocking(false); channel.connect(socketAddress);' – Ali

+0

这个工作,但只有当主机不是IP地址。任何方式让它与IP一起工作呢? – BenCole

0

你发出一个尝试DNS解析?

你可以尝试使用:

public static InetAddress[] getAllByName(String host) 

,但我不确定这是否会要求超时太..

+0

这是通过抛出一个UnknownHostException,但只有当主机不是IP地址。 – BenCole

+0

没看过你有这个要求,对不起 – Jack

2

您需要先创建一个interface在你的类名为NetworkListener,例如

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

接下来,创建一个类,并调用它NetworkStatusThread,例如

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(); 
     } 
    } 

} 

然后就是实例化Thread ,请这样做:

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

另外,在该类中,您需要implementNetworkListener,才能获得回调。

在你上面run()方法,可以实现通过@Ali的代码,但通过我的状态:

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"); 
    } 
+0

谢谢!我以前一直在使用Timer和TimerTask的匿名子类,但我会给这个镜头。 – BenCole

+0

只适用于互联网连接的连接。问题在于网络连接的改变,而不是连接到谷歌 – spy

3

我的程序,需立即告知如果网络连接是 丢失。

运气不好。您无法使用TCP/IP立即收到通知。它充满了缓冲,重试和超时,因此它不会立即执行任何事情,并且TCP通过设计没有与'拨号音'相对应的任何内容,也没有任何API。检测丢失连接的唯一方法是尝试对其执行I/O操作。

我使用Java 5,所以我无法使用 NetworkInterface的非常方便的功能。

他们也不会帮你。他们所能告诉你的只是一个NIC是否已经启动或关闭,而与你与更广泛的世界的联系状态却一无所获。

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; 

如果您处于脱机状态,则会因DNS失败而超时。

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

同上。但是,即使它没有,socket.isConnected()将始终返回true。那些API如isConnected(),isBound(),isClosed(),只会告诉你对套接字做了什么。他们不会告诉你有关连接状态的任何信息。由于我上面给出的原因,他们不能。

而且在发生异常的情况下忘记关闭套接字,所以您有资源泄漏。

我需要一个立即返回的方法。

不可能的原因。你需要重新设计这个功能不存在的认识。

+0

实际上,我能够使用NetworkInterface的功能(我认为)弄清楚了这一点。检查上面的第二个编辑。另外,我不知道你是否看到了,但是在调用'isConnected()'后立即调用'socket.close()'。 – BenCole

+0

如果发生异常,忘记关闭套接字。 – EJP