35

重複の可能性:
インターネット接続がJavaに存在するかどうかを確認する方法は?

Javaを使用しているときにインターネット接続があるかどうかを簡単に検出する方法があるかどうかを知りたいです。現在のアプリは Windows 用の WinInit DLL で "InternetGetConnectedState" メソッドを使用していましたが、私のアプリは Mac 操作用のクロスプラットフォームである必要があり、この方法では機能しません。Java で DLL を使用する JNI もまったく知らず、高速でイライラするようになりました。

私が考えることができる唯一の方法は、Web サイトへの URL 接続を開こうとし、それが失敗した場合は false を返すことでした。私の他の方法は以下ですが、これが一般的に安定しているかどうかはわかりませんでした。ネットワーク ケーブルを抜くと、InetAddress を作成しようとすると UnknownHostException が発生します。それ以外の場合、ケーブルが接続されている場合は、有効な InetAddress オブジェクトを取得します。以下のコードを Mac でまだテストしていません。

あなたが提供できる例やアドバイスをありがとう。

更新: 最終的なコード ブロックは一番下にあります。HTTP リクエスト (この場合は Google) のアドバイスに従うことにしました。シンプルで、返されるデータのサイトにリクエストを送信します。接続からコンテンツを取得できない場合、インターネットはありません。

public static boolean isInternetReachable()
        {
            try {

                InetAddress address = InetAddress.getByName("java.sun.com");

                if(address == null)
                {
                    return false;
                }

            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return false;
            }
            catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return false;
            }
            return true;
        }

最終的なコード ブロック:

//checks for connection to the internet through dummy request
        public static boolean isInternetReachable()
        {
            try {
                //make a URL to a known source
                URL url = new URL("http://www.google.com");

                //open a connection to that source
                HttpURLConnection urlConnect = (HttpURLConnection)url.openConnection();

                //trying to retrieve data from the source. If there
                //is no connection, this line will fail
                Object objData = urlConnect.getContent();

            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return false;
            }
            catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return false;
            }
            return true;
        }
4

7 に答える 7

17

これは、問題を解決するための完全に合理的なアプローチです。悪い点は、ネットワーク全体をテストするのではなく、実際に DNS をテストしていることですが、実際には、それらを同等のものとして扱うことでうまくいくことがよくあります。

もう 1 つ覚えておくべきことは、システム プロパティを設定して、Java ランタイムでの DNS キャッシュをオフにする必要があることです。そうしないと、ネットワークがダウンしていても、キャッシュされたデータに基づいてネットワークがアップしていると報告し続ける可能性があります。

もう 1 つの方法は、このようなネットワーク アドレスへの HTTP 要求を頻繁に実際に開くことです。

于 2009-07-16T18:51:44.840 に答える
11

上記の最終的なコードブロックは良好ですが、1つの欠陥があることを付け加えなければなりません。指定されたアドレスに接続するのに非常に長い時間がかかる可能性がありますが、アドレスには到達できます。

私の例では、1つのアドレスでテストすると、メソッドはtrueを返しますが、応答を取得するのに10秒以上かかります。この場合、サーバーは到達可能でしたが、接続が非常に遅いため、有用な目的には使用できませんでした。これは、のデフォルトのタイムアウトHttpURLConnection0または無限であるために発生します。

このため、UIスレッドをチェックオフし、呼び出すurlConnect.setConnectTimeout(1000); 前に追加することをお勧めしますurlConnect.getContent();

このようにして、アドレスに到達可能であり、10kファイルをダウンロードするのに5年もかからないことがわかります。

(もちろん、ニーズに合わせてタイムアウト時間を変更することもできます)

また、プログラムが一般的に複数のドメインにアクセスする場合を除いて、一般的なアドレス(google.comなど)をチェックしないことをお勧めします。1つまたは2つにアクセスしているだけの場合は、そのドメインを確認してください。

于 2010-07-05T11:47:58.243 に答える
3

java.sun.com が応答しない場合は、false が返される可能性があることに注意してください。この場合、別のサイトを確認してください。

于 2009-07-16T19:03:54.533 に答える
2

最初の解決策の問題は、InetAddress にキャッシュがあることです。そのため、次の数回の呼​​び出しで接続が失われると、Java キャッシュを介して名前が解決されます。URL接続アプローチでは、htmlをフェッチする必要があるgetContentを使用するという問題があるため、データが消費されます。呼び出しが非常に頻繁に行われる場合、それが問題になる可能性があります (ソフトウェアを実行しているデバイスで無制限のデータ プランを使用していない場合はなおさらです)。

最善の解決策は、80 ポートへの TCP 接続を行い、接続が成功した直後にポートを閉じることだと思います。これは最終的なコードとして動作しますが、トラフィックははるかに少なくなります。

于 2010-04-20T20:28:53.087 に答える
2

これはテストしていませんが、java.net.NetworkInterface.getNetworkInterfaces() を見ることをお勧めします。これは、マシン上のすべてのネットワーク インターフェイスの列挙を返します。何もない場合は null を返します。

null 以外の応答が有効なネットワーク接続を保証すると想定するのが安全かどうかはわかりません。必要に応じて、ループバック アドレスを除外する必要がある場合とない場合があります (これは java.net で実行できると思います)。返された NetworkInterface ごとに .NetworkInterface.getInetAddresses() を実行し、それぞれに対して InetAddress.isLoopbackAddress() を呼び出します。)

于 2009-07-16T19:04:14.313 に答える
1

質問に特に意味はありません。「インターネットへの接続」などというものはありません。作成してみる必要があります。参照されている Windows API は、モデムがダイヤルインされているかどうかを示すだけであり、実際にダイヤルインが発生するのを見てきましたが、これは正確なアイデアではありません。過去8年ほどダイヤルインしていたわけではありません。

于 2010-02-19T02:44:55.857 に答える