28

Java プログラムを介して ping を実行しようとしているデバイスがネットワーク上にあります。Windows コマンド プロンプトを使用して、デバイス アドレスに問題なく ping を実行し、そのアドレスに対して tracert を実行できます。

オンラインで、Java を介して ping を実行するには、次の手順を実行する必要があることがわかりました。

InetAddress.getByName(address).isReachable(timeout);

しかし、デバイス アドレスでこのコードを使用すると、プログラムで常に false が返されます。適切なタイムアウト値を持つ正しい IPv4 アドレスを使用しています。また、localhost アドレスを使用すると、正常に動作します。

cmd でデバイスに ping できるのに、プログラムではできないのはなぜですか? これは本当のpingではないという話をいろいろなところで聞きました。

Javaでpingをエミュレートするより良い方法はありますか?

ありがとう

4

9 に答える 9

28

isReachable()特権を取得できる場合はICMP ECHO REQUESTsを使用し、それ以外の場合は宛先ホストのポート 7 (Echo) で TCP 接続を確立しようとします。 したがって、問題はおそらく、クライアント マシンでこれを行うための十分な権限がないという構成の問題か、クライアントに. おそらく両方の場合、これを機能させるには、どちらか一方を解決する必要があります。
ICMP ECHO REQUEST

OSX および Linux クライアントで以下をテストしましたが、他の OSX、Linux、および Windows Server マシンの到達可能性をテストするときに機能します。これをクライアントとして実行するための Windows マシンがありません。

import java.io.IOException;
import java.net.InetAddress;

public class IsReachable
{
    public static void main(final String[] args) throws IOException
    {
        final InetAddress host = InetAddress.getByName(args[0]);
        System.out.println("host.isReachable(1000) = " + host.isReachable(1000));
    }
}

私がここで読んだものから。これは明らかに Windows の制限であり、ICMP PINGWindows 2000 より前のシステム コールとして Windows でサポートされていないため、デフォルトでポート 7 に接続しようとし、「到達」しようとしているマシンでブロックされます。Java は、新しいネイティブ システム コールをまだサポートしていません。ICMPパケットを送信するにはルートが必要なため、パーミッションは Unix ベースのシステム用です。

Windows 2000 以降用の独自の Windows ネイティブJNI ICMP PINGを作成する場合は、IcmpSendEcho Functionがあります。

于 2010-03-15T16:27:37.053 に答える
10

Windows、Linux、および OSX で実際の ICMP ping が必要な場合に、この関数 (この記事から) を使用します (他のシステムはテストしていません)。

public static boolean isReachableByPing(String host) {
    try{
            String cmd = "";
            if(System.getProperty("os.name").startsWith("Windows")) {   
                    // For Windows
                    cmd = "ping -n 1 " + host;
            } else {
                    // For Linux and OSX
                    cmd = "ping -c 1 " + host;
            }

            Process myProcess = Runtime.getRuntime().exec(cmd);
            myProcess.waitFor();

            if(myProcess.exitValue() == 0) {

                    return true;
            } else {

                    return false;
            }

    } catch( Exception e ) {

            e.printStackTrace();
            return false;
    }
}
于 2012-07-28T21:16:40.557 に答える
2

少し遅れましたが、同じことをしようとしているときにこれに出くわしました。

私にとってうまくいった回避策の 1 つは、コマンド ライン ping を直接使用することでした。

    public static boolean ping(String host)
{
    boolean isReachable = false;
    try {
        Process proc = new ProcessBuilder("ping", host).start();

        int exitValue = proc.waitFor();
        System.out.println("Exit Value:" + exitValue);
        if(exitValue == 0)
            isReachable = true;
    } catch (IOException e1) {
        System.out.println(e1.getMessage());
        e1.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return isReachable;
}
于 2011-11-12T13:33:26.497 に答える
1

その問題に関連して書かれた多くの悪いコードを見ました。私のために働いたコードは次のとおりです(サイトは私のコードファイルを正しく解析することを知りません):

public class Test {

    public static boolean isReachablebyPing(String ip) {

        try {
            String command;

        if(System.getProperty("os.name").toLowerCase().startsWith("windows")) {
            // For Windows
            command = "ping -n 2 " + ip;
        } else {
            // For Linux and OSX
            command = "ping -c 2 " + ip;
        }

        Process proc = Runtime.getRuntime().exec(command);
        StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT");
        outputGobbler.start();

        proc.waitFor();
        return checkAvailability(outputGobbler.getOutputLines());

        } catch(IOException | InterruptedException ex) {
        Logger.getLogger(StreamGobbler.class.getName()).log(Level.SEVERE, null, ex);
        }

        return false;
    }

    public static void main(String... args) {

        String ip = "10.20.20.17";   // false in my case
        String ip1 = "10.20.20.100"; // true in my case

        System.out.println(ip + " is avalaible " + isReachablebyPing(ip));
        System.out.println(ip1 + " is avalaible " + isReachablebyPing(ip1));
    }

    private static boolean checkAvailability(List<String> outputLines) {

        for(String line : outputLines) {
            if(line.contains("unreachable")) {
                return false;
            }
            if(line.contains("TTL=")) {
                return true;
            }
        }
        return false;

    }

}

class StreamGobbler extends Thread {

    protected InputStream is;

    protected String type;

    protected List<String> outputLines;

    StreamGobbler(InputStream is, String type) {
        this.is = is;
        this.type = type;
        outputLines = new ArrayList<>();
    }

    public List<String> getOutputLines() {
        return outputLines;
    }

    @Override
    public void run() {
        try {
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line;
            while((line = br.readLine()) != null) {
                outputLines.add(line);
            }
        } catch(IOException ex) {
                Logger.getLogger(StreamGobbler.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
}
于 2013-07-08T11:48:37.517 に答える
1

特権なしで Java から簡単に ping を実行するには、http: //www.icmp4j.org を使用します。

使い方はとても簡単です:

    final IcmpPingRequest request = IcmpPingUtil.createIcmpPingRequest ();

    request.setHost ("www.google.org");

    // repeat a few times

    for (int count = 1; count <= 4; count ++) {

        // delegate

         final IcmpPingResponse response = IcmpPingUtil.executePingRequest (request);

         // log

         final String formattedResponse = IcmpPingUtil.formatResponse (response);

         System.out.println (formattedResponse);

         // rest

         Thread.sleep (1000);

    }
于 2016-03-10T08:49:34.367 に答える