11

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

目前我有两种不同的方法来检查网络连接:
(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;

方法二:

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

但是,这两种方法都会阻塞,直到达到超时,然后才返回 false。我需要一个可以立即返回但与 Java 5 兼容的方法。

谢谢!

编辑:我忘了提到我的程序依赖于 IP 地址,而不是 DNS 名称。因此,在解析主机时检查错误已出...

第二次编辑:

使用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;
                }
            }
        }
4

4 回答 4

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 (Non-blocking IO)

String host = ...; 
InetSocketAddress socketAddress = new InetSocketAddress(host, 80); 
channel = SocketChannel.open(); 
channel.configureBlocking(false); 
channel.connect(socketAddress);
于 2011-08-09T16:14:29.363 回答
4

您需要首先创建一个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();

此外,在该类中,您需要implement,NetworkListener才能获取回调。

在您上面的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");
  }
于 2011-08-09T16:33:47.837 回答
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。像 isConnected()、isBound()、isClosed() 这样的 API 只会告诉你套接字做了什么。他们不会告诉您任何有关连接状态的信息。由于我上面给出的原因,他们不能。

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

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

由于给出的原因是不可能的。您需要围绕该功能不存在的认识进行重新设计。

于 2011-08-10T00:20:05.333 回答
0

您是否尝试过发出 DNS 解析?

您可以尝试:

public static InetAddress[] getAllByName(String host)

但我不确定这是否也需要超时..

于 2011-08-09T16:17:47.127 回答