Javaを使用しているときにインターネット接続があるかどうかを簡単に検出できる方法があるかどうかを知りたいです。現在のアプリは、WinInit DLL for windowsで「InternetGetConnectedState」メソッドを使用していましたが、アプリはMac操作用のクロスプラットフォームである必要があり、この方法は機能しません。 Java=でDLLを使用するためにすべてのいずれかとそれは速くイライラするようになりました。
私が考えることができる唯一の方法は、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;
}
それは問題を解決するための完全に合理的なアプローチです。悪い点は、ネットワーク全体をテストするのではなく、実際にDNSをテストしていることですが、実際には、それらを同等のものとして扱うことで問題を解決できることがよくあります。
もう1つ覚えておくべきことは、JavaランタイムでDNSキャッシングをオフにするためにシステムプロパティを設定する必要があるということです。それ以外の場合、キャッシュされたデータに基づいてネットワークが稼働していることを報告し続ける可能性があります。 (ダウンしている場合でも)。
別のアプローチは、このようなネットワークアドレスへのHTTPリクエストを実際に頻繁に開くことです。
上記の最後のコードブロックは良好ですが、欠点が1つあります。指定されたアドレスにアクセスするのに非常に長い時間がかかる可能性がありますが、アドレスにはまだ到達できます。
私のインスタンスでは、1つのアドレスでテストすると、メソッドはtrueを返しますが、応答を取得するには10秒以上かかります。この場合、サーバーは到達可能でしたが、接続が非常に遅いため、有用な目的ではありませんでした。これは、HttpURLConnection
のデフォルトのタイムアウトが、または無限であるために発生します。
このため、UIスレッドをオフにしてurlConnect.setConnectTimeout(1000);
beforeを呼び出すurlConnect.getContent();
を追加することをお勧めします。
これにより、アドレスに到達可能であり、10kファイルをダウンロードするのに5年もかかりません。
(もちろん、必要に応じてタイムアウト時間を変更することもできます)
また、プログラムが一般に数個を超えるドメインにアクセスしない限り、一般的なアドレス(google.comなど)をチェックしないことをお勧めします。 1つまたは2つにアクセスしているだけの場合は、そのドメインを確認してください。
Java.Sun.comが応答しない場合はfalseを返す可能性があることに注意してください。この場合、他のサイトを確認して確認する必要があります。
最初のソリューションの問題は、InetAddressにキャッシュがあることです。そのため、次の数回の呼び出しで接続が失われると、名前はJavaキャッシュを介して解決されます。URL接続アプローチでは、データを消費するためにhtmlをフェッチするgetContentを使用するという問題です。呼び出しが非常に頻繁に行われる場合は、それが問題になる可能性があります(ソフトウェアを実行しているデバイスに無制限のデータプランがない場合はさらにそうなります)。
最善の解決策は、TCP 80ポートへの接続を行い、接続が成功した直後にポートを閉じることです。これは最終的なコードとして動作しますが、トラフィックははるかに少なくなります。
これはテストしていませんが、Java.net.NetworkInterface.getNetworkInterfaces()を確認することをお勧めします。これは、マシン上のすべてのネットワークインターフェイスの列挙を返すか、ネットワークインターフェイスがない場合はnullを返します。
Null以外の応答が有効なネットワーク接続を保証すると想定しても安全かどうかはわかりません-必要に応じて、ループバックアドレスをフィルタリングする必要がある場合とない場合があります(Java.netで行うことができると思います)返された各NetworkInterfaceで.NetworkInterface.getInetAddresses()を呼び出し、次にそれぞれでInetAddress.isLoopbackAddress()を呼び出します。)
特定のサービスにアクセスできる唯一の方法は、そのサービスに対してダミーのリクエストを行うことです。 pingはファイアウォールによってブロックされる場合があります。到達可能なサーバーもあれば、到達できないサーバーもあります。 Webサービスと通信する必要がある場合は、これらのリクエストに対して返す静的ページを用意してください。
また、連絡を取る前に必ずユーザーに尋ねてください。
質問には意味がありません。 「インターネットへの接続」というものはありません。 create oneを試す必要があります。参照されているWindows APIは、モデムがダイヤルインされているかどうかを通知するだけで、実際には原因ダイヤルインであることがわかりました。私が過去8年ほどダイヤルインしてきたわけではありません。