InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
なぜisReachable
戻るのfalse
ですか?IPにpingを実行できます。
InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
なぜisReachable
戻るのfalse
ですか?IPにpingを実行できます。
「isReachable」メソッドは、多くの場合、私にとって使用する価値がありませんでした。一番下までスクロールして、オンラインで外部ホスト(google.comなど)を解決できるかどうかを簡単にテストするための代替案を確認できます。これは通常、*NIXマシンで機能するようです。
問題
これについてはたくさんのおしゃべりがあります:
他の同様の質問があります:
そして、これと同じ問題について報告されたバグでさえ:
パート1:問題の再現可能な例
この場合、失敗することに注意してください。
//also, this fails for an invalid address, like "www.sjdosgoogle.com1234sd"
InetAddress[] addresses = InetAddress.getAllByName("www.google.com");
for (InetAddress address : addresses) {
if (address.isReachable(10000))
{
System.out.println("Connected "+ address);
}
else
{
System.out.println("Failed "+address);
}
}
//output:*Failed www.google.com/74.125.227.114*
パート2:ハックな回避策
別の方法として、これを行うことができます:
// in case of Linux change the 'n' to 'c'
Process p1 = java.lang.Runtime.getRuntime().exec("ping -n 1 www.google.com");
int returnVal = p1.waitFor();
boolean reachable = (returnVal==0);
pingの-cオプションを使用すると、pingはサーバーに1回だけ到達を試みることができます(ターミナルで使用するのに慣れている無限のpingとは対照的です)。
ホストが到達可能である場合、これは0を返します。それ以外の場合は、戻り値として「2」を取得します。
はるかに単純ですが、もちろん、プラットフォーム固有です。また、このコマンドを使用することには特定の特権の警告があるかもしれませんが、私のマシンでは機能することがわかりました。
注意してください:1)このソリューションは生産品質ではありません。そのちょっとしたハック。グーグルがダウンしている場合、またはインターネットが一時的に遅い場合、あるいは特権/システム設定に多少の面白さがあったとしても、偽陰性を返す可能性があります(つまり、入力アドレスに到達可能であっても失敗する可能性があります)。2)isReachableの失敗は未解決の問題です。繰り返しになりますが、JVMがホストに到達しようとする方法のために、この記事の執筆時点ではこれを行う「完璧な」方法がないことを示すいくつかのオンラインリソースがあります。これは本質的にプラットフォーム固有のタスクであり、単純ですが、JVMによってまだ十分に抽象化されていません。
私はこの同じ質問に対する答えを得るためにここに来ましたが、プラットフォームに依存しないソリューションを探していたため、どの答えにも満足できませんでした。これが私が書いたコードで、プラットフォームに依存しませんが、他のマシン(ほとんどの場合)で開いているポートに関する情報が必要です。
private static boolean isReachable(String addr, int openPort, int timeOutMillis) {
// Any Open port on other machine
// openPort = 22 - ssh, 80 or 443 - webserver, 25 - mailserver etc.
try {
try (Socket soc = new Socket()) {
soc.connect(new InetSocketAddress(addr, openPort), timeOutMillis);
}
return true;
} catch (IOException ex) {
return false;
}
}
更新:この回答に対する最近のコメントに基づいて、上記のコードの簡潔なバージョンを次に示します。
private static boolean isReachable(String addr, int openPort, int timeOutMillis) {
// Any Open port on other machine
// openPort = 22 - ssh, 80 or 443 - webserver, 25 - mailserver etc.
try (Socket soc = new Socket()) {
soc.connect(new InetSocketAddress(addr, openPort), timeOutMillis);
return true;
} catch (IOException ex) {
return false;
}
}
インターネットに接続されているかどうかだけを確認したい場合は、この方法を使用してください。インターネットが接続されている場合はtrueを返します。プログラムを介して接続しようとしているサイトのアドレスを使用する場合は、この方法をお勧めします。
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 (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
他の答えはそうではないので、それを明示的に言及するだけです。isReachable()のping部分には、Unixでのrootアクセスが必要です。そして、4779367のbestsssによって指摘されたように:
また、bashからのpingが実行されない理由を尋ねると、実際には同様に必要です。ls -l / bin/pingを実行します。
私の場合、rootを使用することはできなかったので、解決策は、ファイアウォールのポート7へのアクセスを関心のある特定のサーバーに許可することでした。
2012年に元の質問があったときの状態はわかりません。
現在のところ、pingはルートとして実行されます。ping実行可能ファイルの承認により、+ sフラグと、ルートに属するプロセスが表示されます。これは、ルートとして実行されることを意味します。pingが配置されている場所でls-liatを実行すると、それが表示されます。
したがって、ルートとしてInetAddress.getByName( "www.google.com")。isReacheable(5000)を実行すると、trueが返されます。
ICMP(pingで使用されるプロトコル)で使用されるrawソケットの適切な認証が必要です。
InetAddress.getByNameはpingと同じくらい信頼性がありますが、プロセスを正しく実行するには、プロセスに対する適切なアクセス許可が必要です。
コンピュータにpingを実行できるため、Javaプロセスは、チェックを実行するのに十分な権限で実行する必要があります。おそらく、より低い範囲のポートを使用しているためです。sudo / superuserを使用してJavaプログラムを実行すると、動作するはずです。
インターネット接続をテストする唯一の信頼できる方法は、実際に接続してファイルをダウンロードするか、exec()を介してOSping呼び出しの出力を解析することです。pingの終了コードに依存することはできず、isReachable()はがらくたです。
pingコマンドが正しく実行されると0が返されるため、ping終了コードに依存することはできません。残念ながら、pingはターゲットホストに到達できない場合は正しく実行されますが、ホームADSLルーターから「宛先ホストに到達できません」を取得します。これは、成功したヒットとして扱われる一種の応答であるため、終了コード= 0です。これはWindowsシステム上にあることを追加する必要がありますが、*nixesはチェックされていません。
private boolean isReachable(int nping, int wping, String ipping) throws Exception {
int nReceived = 0;
int nLost = 0;
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("ping -n " + nping + " -w " + wping + " " + ipping);
Scanner scanner = new Scanner(process.getInputStream());
process.waitFor();
ArrayList<String> strings = new ArrayList<>();
String data = "";
//
while (scanner.hasNextLine()) {
String string = scanner.nextLine();
data = data + string + "\n";
strings.add(string);
}
if (data.contains("IP address must be specified.")
|| (data.contains("Ping request could not find host " + ipping + ".")
|| data.contains("Please check the name and try again."))) {
throw new Exception(data);
} else if (nping > strings.size()) {
throw new Exception(data);
}
int index = 2;
for (int i = index; i < nping + index; i++) {
String string = strings.get(i);
if (string.contains("Destination host unreachable.")) {
nLost++;
} else if (string.contains("Request timed out.")) {
nLost++;
} else if (string.contains("bytes") && string.contains("time") && string.contains("TTL")) {
nReceived++;
} else {
}
}
return nReceived > 0;
}
npingは、ネットワークが混雑している場合やシステムがより大きなnping数を選択する場合に、ip(packets)にpingを試行する回数です。 wpingは、ipからのpongを待機する時間です。このメソッドを使用するため
に、2000msに設定できます 。uは次のように記述できます。
isReachable(5, 2000, "192.168.7.93");
または、次のように使用します。
public static boolean exists(final String host)
{
try
{
InetAddress.getByName(host);
return true;
}
catch (final UnknownHostException exception)
{
exception.printStackTrace();
// Handler
}
return false;
}
InetAddress.isReachable
はたるんでいて、pingできるアドレスに対して到達不能を返すことがあります。
私は次のことを試しました:
ping -c 1 <fqdn>
を確認してくださいexit status
。
私が試したすべてのケースで機能しますが、InetAddress.isReachable
機能しません。
インターネットをチェックするには
public boolean isInternetAvailable() {
try {
InetAddress ipAddr = InetAddress.getByName("google.com");
//You can replace it with your name
return !ipAddr.equals("");
} catch (Exception e1) {
try {
Process p1 = java.lang.Runtime.getRuntime().exec("/system/bin/ping -W 1 -c 1 www.google.com");
int returnVal = 0;
returnVal = p1.waitFor();
boolean reachable = (returnVal==0);
return reachable;
} catch (Exception e2) {
e2.printStackTrace();
return false;
}
}
}
ネットワーク接続を確認するには
private boolean isNetworkConnected() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
return cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnected();
}
isReachableはTCPプロトコルを使用しているため(WireSharkによる)PingコマンドはICMPプロトコルを使用しているため、trueを返したい場合は、7ポートを開く必要があります。