IPアドレスにpingできるのに、InetAddress.isReachableがfalseを返すのはなぜですか?


96
InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));

なぜisReachable戻るのfalseですか?IPをpingできます。



1
似ています。問題を解決する手がかりが見つからなかったので、ここでリレイズしました。リマインダーをありがとう!
jiafu 2012年

2
タイムアウトを増やしてみます。
jayunit100 2012

これは非常に良い質問です。十分な賛成票はありません。私が見つけた唯一の同様の質問は、clojure質問としてタグ付けされ、答えは決定的ではありませんでした。
jayunit100 2012

3
誰かが正確にisReachable()が何をしているのか教えてもらえますか?localhostでもfalseを返します...
Seth Keno

回答:


73

「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はサーバーに一度到達することを単純に試みることができます(ターミナルで使用されている無限のpingとは対照的です)。

ホストが到達可能な場合、これは0を返します。そうでない場合、戻り値として「2」が返されます。

はるかに単純ですが、もちろんプラットフォーム固有です。そして、このコマンドを使用することにはいくつかの特権の警告があるかもしれません-私はそれが私のマシンで動作することを発見しました。


注意してください:1)このソリューションは生産品質ではありません。その少しハック。グーグルがダウンしているか、インターネットが一時的に遅い場合、または特権/システム設定にいくつかの機能がある場合でも、偽の否定が返される可能性があります(つまり、入力アドレスに到達可能であっても失敗する可能性があります)。2)isReachableエラーは未解決の問題です。繰り返しますが、JVMがホストに到達しようとする方法が原因で、この記事の執筆時点ではこれを行う「完全な」方法がないことを示すオンラインリソースがいくつかあります。これは本質的にプラットフォーム固有のタスクであり、単純ですが、JVMはまだ十分に抽象化されていません。


@ jayunit100のどちらのアプローチも機能していません、isReachable私は失敗し、pingを使用するとicmpが許可されません?今それをどう扱うか知っていますか?
Yuvi

6
@Yuvi Windowsを使用している場合、フラグは異なります。-cの代わりに-nが必要です。
James T Snell

waitFor()が戻るまでに10秒かかります。Java 7でタイムアウトを言及する方法はありますか?
Jaydev 2017年

@Jaydev、オーバーロードされたオプションもあります:public boolean waitFor(long timeout, TimeUnit unit)java.lang.Process(@since 1.8)
indivisible

2020-01現在、問題の例を問題なく実行でき、1つのIPv4アドレスと1つのIPv6アドレスに対して「接続済み」と報告されています。このバグはJava 5.0 b22でも修正されています。たぶんisReachable今日ではより信頼性があります。
Lii

54

この同じ質問に対する回答を得るためにここに来ましたが、プラットフォームに依存しないソリューションを探していたため、どの回答にも満足できませんでした。これが私が書いたプラットフォームに依存しないコードですが、他のマシンで開いているポートに関する情報が必要です(ほとんどの場合)。

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

2
これは、プラットフォームに依存しない優れたソリューションです。ありがとうございます。
ivandov 2016

1
私はここで終わってうれしいです。スーラブの良い考え方:)
JustADev

だから、私が完全に理解していることを確認するために:例外がない限り、アドレスは到達可能でしたか?
Timmiej93 2016年

1
これは、到達可能性の観点からInetAddress.isReachable()考えられるさまざまなIOExceptions意味について後者がよりインテリジェントであることを除いて、ポート7を介してすでに行っているものと同じです。
ローン侯爵

1
はい@EJP InetAddress.isReachable()標準ライブラリにポート引数を含めるためにオーバーロードされたら素晴らしいと思います。なぜ含まれていなかったのでしょうか?
Sourabh Bhat

7

インターネットに接続されているかどうかを確認するだけの場合は、このメソッドを使用します。インターネットに接続されている場合は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;
    }

2
サーバーにWebサーバーがない場合、それは質問で指定された条件ではありません。
Fran Marzoa 2014

3

他の答えはそうではないので、それを明示的に言及するだけです。isReachable()のping部分には、UNIXでのrootアクセスが必要です。そして、4779367のbestsssによって指摘されたように:

また、bashからのpingが実行されない理由を尋ねると、実際にはそれも必要です。ls -l / bin / pingを実行します。

私の場合、ルートの使用はオプションではなかったので、解決策は、ファイアウォールのポート7へのアクセスを、私が興味を持っていた特定のサーバーに許可することでした。


3

2012年に最初の質問が行われたときの状態はわかりません。

現在のところ、pingはルートとして実行されます。ping実行可能ファイルの承認により、+ sフラグと、rootに属するプロセスが表示されます。つまり、rootとして実行されます。pingが置かれている場所でls -liatを実行すると、表示されるはずです。

したがって、ルートとしてInetAddress.getByName( "www.google.com")。isReacheable(5000)を実行すると、trueが返されます。

ICMP(pingで使用されるプロトコル)で使用されるrawソケットに適切な認証が必要です。

InetAddress.getByNameはpingと同じくらい信頼できますが、プロセスを適切に実行するには、プロセスに対する適切な権限が必要です。


0

インターネット接続をテストする唯一の信頼できる方法は、実際に接続してファイルをダウンロードするか、exec()を介してOS ping呼び出しの出力を解析することです。pingの終了コードに依存することはできず、isReachable()はがらくたです。

pingコマンドが正しく実行されると0が返されるため、ping終了コードに依存することはできません。残念ながら、pingはターゲットホストに到達できない場合でも正しく実行されますが、ホームADSLルーターから「宛先ホストに到達できません」と表示されます。これは、成功したヒットとして扱われる応答の一種なので、終了コード= 0です。これはWindowsシステム上にあることを追加する必要があります。チェックされていません* nixes。


0
 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はping ip(packets)へのpingの試行回数です。ネットワークまたはシステムがビジーな場合は、より大きなnping番号を選択してください。
wpingは、IPからのポンを待つ時間です。
このメソッドを使用するために2000ミリ秒に設定 できます。

isReachable(5, 2000, "192.168.7.93");

コマンドインジェクションの可能性があります。これを実行する前に文字列入力を必ず検証してください
spy

「一般的なエラー」のエラーメッセージもあります。これもウィンドウ固有のように見えます。これらのエラーメッセージはさまざまな言語にローカライズされているので、非常に移植性は高くありません。
スパイ

これはWindowsシステム用です。
Armin Mokri

うん、私は以前にWindowsで見たことがあります
スパイ

0

または、この方法を使用します:

public static boolean exists(final String host)
{
   try
   {
      InetAddress.getByName(host);
      return true;
   }
   catch (final UnknownHostException exception)
   {
      exception.printStackTrace();
      // Handler
   }
   return false;
}

0

InetAddress.isReachable ゆるいです、そして私たちがpingすることができるアドレスのために時々到達不能を返します。

私は以下を試しました:

ping -c 1 <fqdn>を確認してくださいexit status

私が試したすべてのケースでInetAddress.isReachable機能しますが、機能しません。


-1

コンピューターにpingを実行できるため、Javaプロセスは、チェックを実行するための十分な権限で実行する必要があります。おそらく、より低い範囲のポートを使用しているためです。Javaプログラムをsudo / superuserで実行する場合、きっと動作するでしょう。


低範囲のポートに接続する特権は必要ありません。
ローンの侯爵
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.