11

私の問題はかなり簡単です。私のプログラムでは、ネットワーク接続が失われた場合にすぐに通知する必要があります。私はJava5を使用しているので、NetworkInterfaceの非常に便利な機能を使用できません。

現在、ネットワーク接続をチェックする2つの異なる方法があります:
(try..catchesが削除されました)

方法1:

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を返す前にタイムアウトに達するまでブロックします。すぐに戻るメソッドが必要ですが、Java5と互換性があります。

ありがとう!

編集:私のプログラムがDNS名ではなくIPアドレスに依存していることを言及するのを忘れました。したがって、ホストを解決するときにエラーをチェックすることはできません...

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

4 に答える 4

10

JGuruから

Java 5以降、InetAddressクラスにisReachable()メソッドがあります。使用するタイムアウトまたはNetworkInterfaceのいずれかを指定できます。pingで使用される基盤となるインターネット制御メッセージプロトコル(ICMP)の詳細については、RFC 792(http://www.faqs.org/rfcs/rfc792.html)を参照してください。

Java2からの使用

  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);
于 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を実行することです。

私はJava5を使用しているため、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 に答える