Як пінгувати IP-адресу


77

Я використовую цю частину коду для перевірки ip-адреси в Java, але успішним є лише пінг локального хосту, а для інших хостів програма каже, що хост недоступний. Я вимкнув свій брандмауер, але все ще маю цю проблему

public static void main(String[] args) throws UnknownHostException, IOException {
    String ipAddress = "127.0.0.1";
    InetAddress inet = InetAddress.getByName(ipAddress);

    System.out.println("Sending Ping Request to " + ipAddress);
    System.out.println(inet.isReachable(5000) ? "Host is reachable" : "Host is NOT reachable");

    ipAddress = "173.194.32.38";
    inet = InetAddress.getByName(ipAddress);

    System.out.println("Sending Ping Request to " + ipAddress);
    System.out.println(inet.isReachable(5000) ? "Host is reachable" : "Host is NOT reachable");
}

Результат:

Надсилання запиту Ping до 127.0.0.1
Хост недоступний
Відправлення запиту Ping до 173.194.32.38
Хост НЕ доступний


4
Чи можна пінгувати цей сервер, якщо ви використовуєте пінг безпосередньо?
Jenny D

Який вхід ви вводите в jTextField1?
chrisbunney

Так !!! але в моїй програмі я можу лише пінгувати localhost !!!
Мехді,

2
@ user1529128 Я відредагував ваше запитання на простому прикладі, що відтворює поведінку, яку ви описуєте. Не соромтеся відкочувати редагування, якщо ви не думаєте, що це саме те, про що ви просите.
assylias

3
@ assylias: дякую за гарну редакцію! Я новачок у stackoverflow, і це було моє перше питання. Дякую за допомогу.
Мехді,

Відповіді:


15

Ви не можете просто пінгувати на Java, оскільки він покладається на ICMP, який, на жаль, не підтримується в Java

http://mindprod.com/jgloss/ping.html

Замість цього використовуйте розетки

Сподіваюся, це допоможе


Зараз я міг би бути поза контекстом, але це те, що мені вдалося, насправді дуже добре: dnsjava.org Дякую всім.
Равіндранат Акіла

5
Нижче є кращі відповіді
Ігор Зубеньок

@AhmadArslan, яку б відповідь ви не розміщували за цим посиланням, її зараз немає. Отже, посилання вже не дуже корисне ... ви, здається, вбили власне посилання ...
forresthopkinsa

67

InetAddress.isReachable()згідно javadoc :

".. Типова реалізація використовуватиме ICMP ECHO REQUESTs, якщо привілей можна отримати, інакше вона намагатиметься встановити TCP-з'єднання через порт 7 (Echo) цільового хоста ..".

Варіант №1 (ICMP) зазвичай вимагає адміністративних (root)прав.


3
Тоді чому ви зазвичай можете робити це як не адміністратор / некореневий користувач на більшості комп’ютерів поза Java ?
Loduwijk

Щоб пояснити: Чи використовують такі команди, як пінг командного рядка, використання ICMP-пакетів? Я був певен, що вони це зробили. Чи виконується ping в адміністративному контексті?
Loduwijk

Ви хочете сказати, що метод isReachable використовує ТІЛЬКИ TCP-порт 7, і він НЕ використовуватиме ICMP ECHO REQUESTs? Або він буде використовувати ICMP, якщо я якось надаю привілеї root для моєї програми? Якщо останнє, то як я можу дозволити моєму додатку працювати як root?
Майкл Сімс

9
pingКоманда на Linux є UID посадженого кореня; саме тому некореневі користувачі можуть використовувати його, навіть якщо він використовує ICMP ECHO_REQUEST.
erickson,

1
Це насправді погано працює: stackoverflow.com/questions/9922543/…
Етан Мік,

33

Я думаю, що цей код допоможе вам:

public class PingExample {
    public static void main(String[] args){
        try{
            InetAddress address = InetAddress.getByName("192.168.1.103");
            boolean reachable = address.isReachable(10000);

            System.out.println("Is host reachable? " + reachable);
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

20

Перевірте підключення. На моєму комп'ютері це друкує REACHABLE для обох IP-адрес:

Надсилання запиту Ping до 127.0.0.1
Хост доступний
Відправлення запиту Ping до 173.194.32.38
Хост доступний

РЕДАГУВАТИ:

Ви можете спробувати змінити код, щоб використовувати getByAddress () для отримання адреси:

public static void main(String[] args) throws UnknownHostException, IOException {
    InetAddress inet;

    inet = InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 });
    System.out.println("Sending Ping Request to " + inet);
    System.out.println(inet.isReachable(5000) ? "Host is reachable" : "Host is NOT reachable");

    inet = InetAddress.getByAddress(new byte[] { (byte) 173, (byte) 194, 32, 38 });
    System.out.println("Sending Ping Request to " + inet);
    System.out.println(inet.isReachable(5000) ? "Host is reachable" : "Host is NOT reachable");
}

Методи getByName () можуть робити спроби зворотного пошуку DNS, що може бути неможливим на вашому комп'ютері, getByAddress () може обійти це.


Я впевнений, що підключений, і навіть вимкнув брандмауер та антивірус, але все одно це не працює ...
Мехді,

Це все ще може бути ваша машина. В якій ОС ви працюєте? Ви пробували метод getByAddress () замість методу getByName (), щоб переконатись, що не здійснюється спроба зворотного пошуку DNS?
Дурандаль,

@ Durandal Я використовую win7 і так! Я спробував getByAddress () замість getByName (), не було спроб пошуку DNS, не кажіть мені, що для мене немає можливості, будь ласка!
Мехді,

1
@Durandal: чому нам потрібно ввести привід ipaddress у байт у другому прикладі, який ви навели?
Vamsi Pavan Mahesh

3
@vamsi Оскільки IP надається як літерали, а компілятор вважає, що літерали мають тип int. Оскільки діапазон значень байтів становить від -128 до 127, значення поза цим діапазоном вимагають явного приведення (наприклад, літерал 173). Причина "чому" кореняться в підписаному байте Java, а IP-адреси зазвичай представляються як непідписані байти для читабельності.
Дурандаль,

11

Це точно спрацює

import java.io.*;
import java.util.*;

public class JavaPingExampleProgram
{

  public static void main(String args[]) 
  throws IOException
  {
    // create the ping command as a list of strings
    JavaPingExampleProgram ping = new JavaPingExampleProgram();
    List<String> commands = new ArrayList<String>();
    commands.add("ping");
    commands.add("-c");
    commands.add("5");
    commands.add("74.125.236.73");
    ping.doCommand(commands);
  }

  public void doCommand(List<String> command) 
  throws IOException
  {
    String s = null;

    ProcessBuilder pb = new ProcessBuilder(command);
    Process process = pb.start();

    BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
    BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));

    // read the output from the command
    System.out.println("Here is the standard output of the command:\n");
    while ((s = stdInput.readLine()) != null)
    {
      System.out.println(s);
    }

    // read any errors from the attempted command
    System.out.println("Here is the standard error of the command (if any):\n");
    while ((s = stdError.readLine()) != null)
    {
      System.out.println(s);
    }
  }

}

1
Якщо ви перейдете -cна -n, швидше за все.
Кодінгейл

2
@Supuhstar це буде працювати лише в ОС, яка має команду ping. В основному те, що він робить вище, це розгалужити новий процес і змусити його запустити pingкоманду з ОС.
Harry Cho

10

Ви можете використовувати цей метод для пінгування хостів у Windows та інших платформах:

private static boolean ping(String host) throws IOException, InterruptedException {
    boolean isWindows = System.getProperty("os.name").toLowerCase().contains("win");

    ProcessBuilder processBuilder = new ProcessBuilder("ping", isWindows? "-n" : "-c", "1", host);
    Process proc = processBuilder.start();

    int returnVal = proc.waitFor();
    return returnVal == 0;
}

У вікнах ви завжди отримуєте 1 як returnVal. Незалежно від того, доступний він чи ні.
ssindelar

Мав успіх у цьому як на Windows, так і на Android
Frederik Witte

5

коротка рекомендація: не використовуйте isReachable (), зателефонуйте системному пінгу, як пропонується у деяких відповідях вище.

довге пояснення:

  • ping використовує протокол мережі ICMP. Щоб використовувати ICMP, потрібен `` сирий сокет ''
  • стандартним користувачам операційна система не дозволяє використовувати необроблені сокети
  • наступне стосується Fedora 30 Linux, системи Windows повинні бути подібними
  • якщо Java працює як root, isReachable () насправді надсилає запити пінгу ICMP
  • якщо java не працює як root, isReachable () намагається підключитися до TCP-порту 7, відомого як echo-порт. Ця послуга зазвичай більше не використовується, її спроба може дати неправильні результати
  • будь-яка відповідь на запит на підключення, а також відхилення (прапор TCP RST) дає 'true' з isReachable ()
  • деякі брандмауери надсилають RST для будь-якого порту, який явно не відкритий. Якщо це станеться, ви отримаєте isReachable () == true для хосту, який навіть не існує
  • далі намагається призначити необхідні можливості процесу Java:
  • setcap cap_net_raw + виконуваний файл eip java (призначити право на використання необроблених сокетів)
  • тест: виконуваний файл getcap java -> 'cap_net_raw + eip' (можливість призначена)
  • запущена Java все ще надсилає запит TCP на порт 7
  • перевірка запущеного процесу Java за допомогою getpcaps pid показує, що запущений java не має можливостей вихідного сокета. Очевидно, мій встановлений обмеження був замінений якимось механізмом безпеки
  • оскільки вимоги до безпеки зростають, це, ймовірно, стане ще більш обмеженим, якщо sb не реалізує виняток, особливо для пінгу (але в мережі поки що нічого не знайдено)

3


Просто доповнення до того, що дали інші, хоча вони працюють добре, але в деяких випадках, якщо Інтернет працює повільно або існує якась невідома мережева проблема, деякі коди не працюватимуть ( isReachable()). Але цей код, згаданий нижче, створює процес, який діє як командний рядок ping (cmd ping) для windows. Це працює для мене у всіх випадках, перевірено.

Код: -

public class JavaPingApp {

public static void runSystemCommand(String command) {

    try {
        Process p = Runtime.getRuntime().exec(command);
        BufferedReader inputStream = new BufferedReader(
                new InputStreamReader(p.getInputStream()));

        String s = "";
        // reading output stream of the command
        while ((s = inputStream.readLine()) != null) {
            System.out.println(s);
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static void main(String[] args) {

    String ip = "stackoverflow.com"; //Any IP Address on your network / Web
    runSystemCommand("ping " + ip);
}
}

Сподіваюся, це допоможе, ура !!!


це може бути вразливим для введення команди, завжди перевіряти введення
шпигун

3

Незважаючи на те, що це не покладається на ICMP у Windows, ця реалізація працює досить добре з новим API тривалості

public static Duration ping(String host) {
    Instant startTime = Instant.now();
    try {
        InetAddress address = InetAddress.getByName(host);
        if (address.isReachable(1000)) {
            return Duration.between(startTime, Instant.now());
        }
    } catch (IOException e) {
        // Host not available, nothing to do here
    }
    return Duration.ofDays(1);
}

1

У linux з oracle-jdk код, який передає OP, використовує порт 7, коли він не є root, а ICMP - коли root Він робить справжній запит ехо-сигналу ICMP при запуску від імені користувача, як зазначено в документації.

Якщо ви запускаєте це на машині MS, можливо, вам доведеться запустити програму як адміністратор, щоб отримати поведінку ICMP.


1

Ось метод для діагностики IP - адреса в Javaтому , що повинні працювати Windowsі Unixсистем:

import org.apache.commons.lang3.SystemUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class CommandLine
{
    /**
     * @param ipAddress The internet protocol address to ping
     * @return True if the address is responsive, false otherwise
     */
    public static boolean isReachable(String ipAddress) throws IOException
    {
        List<String> command = buildCommand(ipAddress);
        ProcessBuilder processBuilder = new ProcessBuilder(command);
        Process process = processBuilder.start();

        try (BufferedReader standardOutput = new BufferedReader(new InputStreamReader(process.getInputStream())))
        {
            String outputLine;

            while ((outputLine = standardOutput.readLine()) != null)
            {
                // Picks up Windows and Unix unreachable hosts
                if (outputLine.toLowerCase().contains("destination host unreachable"))
                {
                    return false;
                }
            }
        }

        return true;
    }

    private static List<String> buildCommand(String ipAddress)
    {
        List<String> command = new ArrayList<>();
        command.add("ping");

        if (SystemUtils.IS_OS_WINDOWS)
        {
            command.add("-n");
        } else if (SystemUtils.IS_OS_UNIX)
        {
            command.add("-c");
        } else
        {
            throw new UnsupportedOperationException("Unsupported operating system");
        }

        command.add("1");
        command.add(ipAddress);

        return command;
    }
}

Обов’язково додайте Apache Commons Langдо своїх залежностей.


цей приклад може не працювати в неанглійських операційних системах. На вікнах також є повідомлення про помилку "загальна невдача", а можуть бути й інші
шпигун

0

Я знаю, що на це відповідали попередні записи, але для будь-кого іншого, хто приходить до цього питання, я знайшов спосіб, який не вимагав використання процесу "ping" у вікнах, а потім очищення результатів.

Те, що я зробив, було використання JNA для виклику допоміжної бібліотеки Window для виконання відлуння ICMP

Подивіться мою власну відповідь на моє власне подібне питання


0

InetAddress не завжди повертає правильне значення. Це успішно у випадку локального хосту, але для інших хостів це показує, що хост недоступний. Спробуйте скористатися командою ping, як показано нижче.

try {
    String cmd = "cmd /C ping -n 1 " + ip + " | find \"TTL\"";        
    Process myProcess = Runtime.getRuntime().exec(cmd);
    myProcess.waitFor();

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

    return true;
    }
    else {
        return false;
    }
}
catch (Exception e) {
    e.printStackTrace();
    return false;
}

0

Я спробував кілька варіантів:

  1. Java InetAddress

InetAddress.getByName(ipAddress), мережа на вікнах почала неправильно поводитися після декількох спроб

  1. Java HttpURLConnection

            URL siteURL = new URL(url);
            connection = (HttpURLConnection) siteURL.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(pingTime);
            connection.connect();
    
            code = connection.getResponseCode();
            if (code == 200) {
                code = 200;
            }.
    

Це було надійно, але трохи повільно

  1. Пакетний файл Windows

Нарешті я вирішив створити пакетний файл на моїй машині Windows із таким вмістом: ping.exe -n %echoCount% %pingIp% Потім я зателефонував до файлу .bat у своєму коді Java за допомогою

public int pingBat(Network network) {
ProcessBuilder pb = new ProcessBuilder(pingBatLocation);
Map<String, String> env = pb.environment();

env.put(
        "echoCount", noOfPings + "");
env.put(
        "pingIp", pingIp);
File outputFile = new File(outputFileLocation);
File errorFile = new File(errorFileLocation);

pb.redirectOutput(outputFile);

pb.redirectError(errorFile);

Process process;

try {
    process = pb.start();
    process.waitFor();
    String finalOutput = printFile(outputFile);
    if (finalOutput != null && finalOutput.toLowerCase().contains("reply from")) {
        return 200;
    } else {
        return 202;
    }
} catch (IOException e) {
    log.debug(e.getMessage());
    return 203;
} catch (InterruptedException e) {
    log.debug(e.getMessage());
    return 204;
}

}

Це виявилося найшвидшим і надійним способом


1
Пакетний приклад неправильний. Результатом може бути "відповідь від xyza: Кінцевий хост недосяжний", що поверне позитивну відповідь.
шпигун

0

Я віддаю перевагу цьому:

   /**
     *
     * @param host
     * @return true means ping success,false means ping fail.
     * @throws IOException
     * @throws InterruptedException
     */
    private static boolean ping(String host) throws IOException, InterruptedException {
        boolean isWindows = System.getProperty("os.name").toLowerCase().contains("win");

        ProcessBuilder processBuilder = new ProcessBuilder("ping", isWindows? "-n" : "-c", "1", host);
        Process proc = processBuilder.start();
        return proc.waitFor(200, TimeUnit.MILLISECONDS);
    }

Цей спосіб може обмежити час блокування певним часом, наприклад 200 мс.

Він добре працює в MacOS 、 Android та Windows, але повинен використовуватися в JDK 1.8.

Ця ідея походить від Мохаммада Банісейда , але я не можу коментувати. (Ви повинні мати 50 репутації, щоб коментувати)


-3

Це має спрацювати:

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Pinger {

private static String keyWordTolookFor = "average";

public Pinger() {
    // TODO Auto-generated constructor stub
}


 public static void main(String[] args) {
 //Test the ping method on Windows.
 System.out.println(ping("192.168.0.1")); }


public String ping(String IP) {
    try {
        String line;
        Process p = Runtime.getRuntime().exec("ping -n 1 " + IP);
        BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
        while (((line = input.readLine()) != null)) {

            if (line.toLowerCase().indexOf(keyWordTolookFor.toLowerCase()) != -1) {

                String delims = "[ ]+";
                String[] tokens = line.split(delims);
                return tokens[tokens.length - 1];
            } 
        }

        input.close();
    } catch (Exception err) {
        err.printStackTrace();
    }
    return "Offline";
}

}


4
Будь ласка, додайте опис того, як працює ваш код. Це допоможе ОП зрозуміти ваш код, коли він його застосує.
Зайнятий програміст 02.03.17

Доводилося це переглядати в "черзі низької якості" ... Але оскільки воно датується годину ... Можливо, незабаром це буде покращено за допомогою пояснень. Що поспішає розмістити відповідь на питання 2012 року? Ну ... поки що я просто пропускаю це.
Луїс Патріс Бессетт

Дякуємо за всі ваші коментарі. Перш за все це клас і метод роботи ТІЛЬКИ з вікнами. Мені потрібно було пінг-час для проекту, тому я придумав це, що брудно, але швидко, якщо ви працюєте на вікнах. Це дуже швидкий ~ 5 хв розроблений код для пінгування хосту IPv4, як ви можете бачити з самого коду. Цей клас і його метод отримує String як IP-адресу та повертає середній час для пінгу, який генерується у CMD Windows. CMD - це те, що ping і цей код зчитує вихідні дані, щоб дійти до рядка, в якому подано деяку числову статистику.
Джон Сміт

Він "токенізує" результат, коли задано min, max і середнє, і повертає середній час. Це трохи божевільно, що ви можете мати середній час лише з одного пінгу, але це windows, і він все одно робить це.
Джон Сміт

Будь ласка, спробуйте це на собі в Windows, перш ніж позначити його. Це легке / брудне виправлення для великої проблеми.
Джон Сміт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.