So pingen Sie eine IP-Adresse

77

Ich verwende diesen Teil des Codes, um eine IP-Adresse in Java zu pingen, aber nur das Pingen von localhost ist erfolgreich und für die anderen Hosts sagt das Programm, dass der Host nicht erreichbar ist. Ich habe meine Firewall deaktiviert, habe aber immer noch dieses Problem

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

Die Ausgabe ist:

Senden einer Ping-Anfrage an 127.0.0.1
Host ist erreichbar
Senden einer Ping-Anfrage an 173.194.32.38
Host ist NICHT erreichbar

Mehdi
quelle
4
Ist es möglich, diesen Server zu pingen, wenn Sie Ping direkt verwenden?
Jenny D
Welche Eingabe geben Sie in jTextField1 ein?
Chrisbunney
Ja !!! aber in meinem programm kann ich nur localhost pingen !!!
Mehdi
2
@ user1529128 Ich habe Ihre Frage mit einem einfachen Beispiel bearbeitet, das das von Ihnen beschriebene Verhalten reproduziert. Sie können die Bearbeitung jederzeit rückgängig machen, wenn Sie nicht der Meinung sind, dass dies das ist, wonach Sie fragen.
Assylias
3
@ assylias: danke für deine nette redaktion! Ich bin neu bei Stackoverflow und das war meine erste Frage. Danke, dass du mir geholfen hast.
Mehdi

Antworten:

16

Sie können nicht einfach in Java pingen, da es auf ICMP basiert, das in Java leider nicht unterstützt wird

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

Verwenden Sie stattdessen Steckdosen

Ich hoffe es hilft

Aretai
quelle
Ich könnte jetzt aus dem Zusammenhang geraten , aber das hat bei mir sehr gut funktioniert : dnsjava.org Vielen Dank an alle.
Ravindranath Akila
5
Es gibt bessere Antworten unten
Igor Zubchenok
@AhmadArslan Welche Antwort Sie auch immer unter diesem Link gepostet haben, sie ist jetzt weg. Der Link ist also nicht mehr wirklich hilfreich ... Sie scheinen Ihren eigenen Link getötet zu haben ...
forresthopkinsa
65

InetAddress.isReachable()laut javadoc :

".. Eine typische Implementierung verwendet ICMP ECHO REQUESTs, wenn das Privileg erhalten werden kann, andernfalls wird versucht, eine TCP-Verbindung an Port 7 (Echo) des Zielhosts herzustellen."

Option 1 (ICMP) erfordert normalerweise Administratorrechte (root).

Arvik
quelle
3
Warum können Sie dies dann normalerweise als Nicht-Administrator / Nicht-Root auf den meisten Computern außerhalb von Java tun ?
Loduwijk
Zur Verdeutlichung: Verwenden Befehle wie Befehlszeilen-Ping keine ICMP-Pakete? Ich war mir ziemlich sicher, dass sie es taten. Wird Ping in einem administrativen Kontext ausgeführt?
Loduwijk
Wollen Sie damit sagen, dass die isReachable-Methode NUR TCP-Port 7 verwendet und KEINE ICMP-ECHO-ANFRAGEN verwendet? Oder wird ICMP verwendet, wenn ich meiner Anwendung irgendwie Root-Rechte erteile? Wenn letzteres der Fall ist, wie kann ich dann zulassen, dass meine App als Root ausgeführt wird?
Michael Sims
9
Der pingBefehl unter Linux lautet set-uid root. Aus diesem Grund können Nicht-Root-Benutzer es verwenden, obwohl es ICMP ECHO_REQUEST verwendet.
Erickson
1
Das funktioniert nicht wirklich gut: stackoverflow.com/questions/9922543/…
Ethan Mick
32

Ich denke, dieser Code wird Ihnen helfen:

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();
        }
    }
}
mohammad shojaeinia
quelle
19

Überprüfen Sie Ihre Konnektivität. Auf meinem Computer wird REACHABLE für beide IPs gedruckt:

Senden einer Ping-Anfrage an 127.0.0.1
Host ist erreichbar
Senden einer Ping-Anfrage an 173.194.32.38
Host ist erreichbar

BEARBEITEN:

Sie können versuchen, den Code so zu ändern, dass er getByAddress () verwendet, um die Adresse zu erhalten:

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

Die Methoden getByName () versuchen möglicherweise eine umgekehrte DNS-Suche, die auf Ihrem Computer möglicherweise nicht möglich ist. GetByAddress () umgeht dies möglicherweise.

Durandal
quelle
Ich bin sicher, dass ich verbunden bin und sogar meine Firewall und mein Antivirus deaktiviert habe, aber es funktioniert immer noch nicht ...
Mehdi
Es kann immer noch Ihre Maschine sein. Auf welchem ​​Betriebssystem bist du? Haben Sie die Methode getByAddress () anstelle der Methode getByName () ausprobiert, um sicherzustellen, dass keine umgekehrte DNS-Suche versucht wird?
Durandal
@ Durandal Ich benutze Win7 und ja! Ich habe getByAddress () anstelle von getByName () ausprobiert. Es gab keinen DNS-Suchversuch. Sagen Sie mir bitte nicht, dass es für mich keinen Weg gibt!
Mehdi
1
@ Durandal: Warum müssen wir im zweiten Beispiel, das Sie angegeben haben, cast the ipaddress to byte eingeben?
Vamsi Pavan Mahesh
3
@vamsi Da die IP als Literale angegeben wird und Literale vom Compiler als vom Typ int betrachtet werden. Da der Wertebereich von Byte -128 bis 127 beträgt, erfordern Werte außerhalb dieses Bereichs eine explizite Umwandlung (z. B. Literal 173). Das "Warum" wurzelt in javas Bytes, die signiert werden, und IP-Adressen werden normalerweise zur besseren Lesbarkeit als vorzeichenlose Bytes dargestellt.
Durandal
12

Es wird sicher funktionieren

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

}
gYanI
quelle
1
Wenn Sie ändern -czu -n, am wahrscheinlichsten.
Codingale
2
@Supuhstar funktioniert nur unter Betriebssystemen mit Ping-Befehl. Grundsätzlich wird oben ein neuer Prozess verzweigt und der pingBefehl vom Betriebssystem ausgeführt.
Harry Cho
9

Mit dieser Methode können Sie Hosts unter Windows und anderen Plattformen anpingen:

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;
}
Mohammad Banisaeid
quelle
Unter Windows erhalten Sie immer 1 als returnVal. Egal ob es erreichbar ist oder nicht.
ssindelar
Hatte Erfolg damit sowohl auf Windows als auch auf Android
Frederik Witte
4

kurze Empfehlung: Verwenden Sie nicht isReachable (), sondern rufen Sie den System-Ping auf, wie in einigen der obigen Antworten vorgeschlagen.

lange Erklärung:

  • ping verwendet das ICMP-Netzwerkprotokoll. Um ICMP verwenden zu können, wird ein "Raw-Socket" benötigt
  • Standardbenutzer dürfen vom Betriebssystem keine Raw-Sockets verwenden
  • Für Fedora 30 Linux gilt Folgendes: Windows-Systeme sollten ähnlich sein
  • Wenn Java als Root ausgeführt wird, sendet isReachable () tatsächlich ICMP-Ping-Anforderungen
  • Wenn Java nicht als Root ausgeführt wird, versucht isReachable (), eine Verbindung zum TCP-Port 7 herzustellen, der als Echo-Port bezeichnet wird. Dieser Dienst wird normalerweise nicht mehr verwendet. Wenn Sie versuchen, ihn zu verwenden, kann dies zu falschen Ergebnissen führen
  • Jede Art von Antwort auf die Verbindungsanforderung, auch eine Zurückweisung (TCP-Flag RST), ergibt ein 'true' von isReachable ()
  • Einige Firewalls senden RST für jeden Port, der nicht explizit geöffnet ist. In diesem Fall erhalten Sie isReachable () == true für einen Host, der noch nicht einmal existiert
  • versucht ferner, einem Java-Prozess die erforderlichen Funktionen zuzuweisen:
  • setcap cap_net_raw + eip java ausführbare Datei (das Recht zur Verwendung von Raw-Sockets zuweisen)
  • Test: Getcap Java ausführbare Datei -> 'cap_net_raw + eip' (Fähigkeit ist zugewiesen)
  • Das laufende Java sendet weiterhin eine TCP-Anfrage an Port 7
  • Die Überprüfung des laufenden Java-Prozesses mit getpcaps pid zeigt, dass der laufende Java nicht über die Raw-Socket-Fähigkeit verfügt. Offensichtlich wurde meine Setcap durch einen Sicherheitsmechanismus überschrieben
  • Da die Sicherheitsanforderungen steigen, wird dies wahrscheinlich noch eingeschränkter, es sei denn, sb implementiert eine Ausnahme speziell für Ping (aber bisher nichts im Netz gefunden).
eci
quelle
3


Nur eine Ergänzung zu dem, was andere gegeben haben, obwohl sie gut funktionieren, aber in einigen Fällen, wenn das Internet langsam ist oder ein unbekanntes Netzwerkproblem vorliegt, funktionieren einige der Codes nicht ( isReachable()). Dieser unten erwähnte Code erstellt jedoch einen Prozess, der als Befehlszeilen-Ping (cmd-Ping) für Windows fungiert. Es funktioniert bei mir in allen Fällen bewährt.

Code: -

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

Hoffe es hilft, Prost !!!

mustangDC
quelle
Dies könnte auf Befehl der Injektion immer bestätigt die Eingabe anfällig sein
Spion
3

Obwohl dies nicht auf ICMP unter Windows beruht, funktioniert diese Implementierung mit der neuen Duration-API recht gut

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);
}
Hieronymus
quelle
1

Unter Linux mit oracle-jdk verwendet der vom OP übermittelte Code Port 7, wenn nicht root, und ICMP, wenn root. Es führt eine echte ICMP-Echoanforderung aus, wenn es als Root ausgeführt wird, wie in der Dokumentation angegeben.

Wenn Sie dies auf einem MS-Computer ausführen, müssen Sie möglicherweise die App als Administrator ausführen, um das ICMP-Verhalten zu erhalten.

user176495
quelle
1

Hier ist eine Methode zum Pingen einer IP-Adresse Java, die auf Windowsund auf UnixSystemen funktionieren sollte:

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

Stellen Sie sicher, dass Sie Apache Commons LangIhre Abhängigkeiten hinzufügen .

BullyWiiPlaza
quelle
Dieses Beispiel funktioniert möglicherweise nicht unter nicht englischen Betriebssystemen. Unter Windows gibt es auch die Fehlermeldung "Allgemeiner Fehler" und möglicherweise andere
Spion
0

Ich weiß, dass dies mit früheren Einträgen beantwortet wurde, aber für alle anderen, die zu dieser Frage kommen, habe ich einen Weg gefunden, bei dem es nicht erforderlich war, den "Ping" -Prozess in Windows zu verwenden und dann die Ausgabe zu bereinigen.

Ich habe JNA verwendet, um die IP-Hilfsbibliothek von Window aufzurufen und ein ICMP-Echo zu erzeugen

Siehe meine eigene Antwort auf mein eigenes ähnliches Problem

Jgregoire108
quelle
0

InetAddress gibt nicht immer den richtigen Wert zurück. Dies ist im Fall eines lokalen Hosts erfolgreich, aber für andere Hosts zeigt dies, dass der Host nicht erreichbar ist. Versuchen Sie es mit dem unten angegebenen Ping-Befehl.

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;
}
Suganya Vinayakam
quelle
0

Ich habe ein paar Optionen ausprobiert:

  1. Java InetAddress

InetAddress.getByName(ipAddress)Das Netzwerk unter Windows begann sich nach einigen Versuchen schlecht zu benehmen

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

Das war zuverlässig, aber etwas langsam

  1. Windows-Batchdatei

Ich habe mich schließlich entschlossen, auf meinem Windows-Computer eine Batch-Datei mit folgendem Inhalt zu erstellen: ping.exe -n %echoCount% %pingIp% Dann habe ich die .bat-Datei in meinem Java-Code mit aufgerufen

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

}}

Dies erwies sich als der schnellste und zuverlässigste Weg

Felix Oriedo
quelle
1
Das Batch-Beispiel ist nicht richtig. Die Ausgabe kann leicht "Antwort von xyza: Zielhost nicht erreichbar" sein, was eine positive Antwort zurückgeben würde.
Spion
0

Ich bevorzuge diesen Weg:

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

Auf diese Weise kann die Blockierungszeit auf die bestimmte Zeit begrenzt werden, z. B. 200 ms.

Es funktioniert gut unter MacOS, Android und Windows, sollte aber in JDK 1.8 verwendet werden.

Diese Idee stammt von Mohammad Banisaeid , aber ich kann nichts dazu sagen . (Sie müssen 50 Ruf haben, um zu kommentieren)

Fischer
quelle
-3

Das sollte funktionieren:

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

}}

John Smith
quelle
4
Bitte fügen Sie eine Beschreibung der Funktionsweise Ihres Codes hinzu. Es wird OP helfen, Ihren Code zu verstehen, wenn er ihn anwendet.
BusyProgrammer
Hatte dies in der "Warteschlange von geringer Qualität" zu überprüfen ... Aber da es aus einer Stunde stammt ... Vielleicht wird es bald mit Erklärungen verbessert. Was ist die Eile, eine Antwort auf eine Frage von 2012 zu veröffentlichen? Nun ... ich überspringe es jetzt einfach.
Louys Patrice Bessette
Vielen Dank für all Ihre Kommentare. Zuallererst ist dies eine Klasse und Methode, um NUR mit Windows zu arbeiten. Ich brauchte eine Ping-Zeit für ein Projekt, also kam ich auf diese Idee, die schmutzig, aber schnell ist, wenn Sie an Fenstern arbeiten. Dies ist ein superschneller ~ 5-minütiger Code zum Pingen eines IPv4-Hosts, wie Sie aus dem Code selbst ersehen können. Diese Klasse und ihre Methode erhalten einen String als IP-Adresse und geben die durchschnittliche Zeit für den Ping zurück, der in Windows CMD generiert wird. CMD die den Ping und dieser Code liest die Ausgabe, um zu der Zeile zu gelangen, in der einige numerische Statistiken angegeben sind.
John Smith
Es "tokenisiert" die Ausgabe, wenn min, max und Durchschnitt angegeben sind, und gibt die durchschnittliche Zeit zurück. Es ist ein bisschen verrückt, dass man mit nur einem Ping eine durchschnittliche Zeit haben kann, aber das sind Fenster und es macht es trotzdem.
John Smith
Bitte probieren Sie es selbst unter Windows aus, bevor Sie es markieren. Es ist eine einfache / schmutzige Lösung für ein großes Problem.
John Smith