2010-03-15 16 views
28

Mam urządzenie w sieci, które próbuję wykonać polecenie ping przez mój program Java. Przez okno poleceń systemu Windows mogę pingować adres urządzenia w porządku i wykonać polecenie tracert na grzywnie adresu.Jak wykonać prawdziwy ping w języku Java z systemu Windows?

Online, widziałem, że w tym celu ping poprzez Java trzeba wykonać następujące czynności:

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

ale kiedy używam tego kodu na mój adres urządzenia, zawsze zwraca fałsz w moim program. Używam poprawnego adresu IPv4 z dobrą wartością limitu czasu. Ponadto, jeśli używam adresu localhost, działa poprawnie.

Dlaczego mogę pingować urządzenie przez cmd, ale nie przez mój program? Słyszałem w różnych miejscach, że to nie jest ping.

Czy istnieje lepszy sposób emulacji ping w Javie?

Dzięki

Odpowiedz

27

isReachable() użyje ICMP ECHO REQUEST s czy uprawnienia można uzyskać, w przeciwnym razie będzie starał się nawiązać połączenia TCP na porcie 7 (ECHO) hosta docelowego.
W związku z tym problem stanowi prawdopodobnie problem z konfiguracją niewystarczających uprawnień do wykonania tej czynności na komputerze klienta lub problem z portem 7 na serwerze, jeśli klient nie ma uprawnień do wykonywania funkcji ICMP ECHO REQUEST. Prawdopodobnie w obu przypadkach musisz rozwiązać jedną lub drugą stronę, aby to zadziałało.

Testowałem następujące produkty na klientach z systemem OSX i Linux i działają one w przypadku testowania dostępności innych komputerów z systemem OSX, Linux i Windows Server. Nie mam komputera z systemem Windows, aby uruchomić to jako klient.

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

z tego, co przeczytałem here. Najwyraźniej jest to ograniczenie Windows i ICMP PING nie jest obsługiwane w systemie Windows jako wywołanie systemowe wcześniejsze niż Windows 2000, więc domyślnie próbuje połączyć się z portem 7 i jest zablokowane na komputerze, do którego próbujesz się "zbliżyć". Java nie obsługuje jeszcze nowego natywnego wywołania systemowego. Zezwolenie dotyczy systemu opartego na systemie Unix, ponieważ wymagają one root do wysyłania pakietów ICMP.

Jeśli chcesz przetasować własny system operacyjny Windows JNIICMP PING dla systemu Windows 2000 i nowszego, jest to IcmpSendEcho Function.

+1

... ale mogę to zrobić za pośrednictwem wiersza polecenia systemu Windows przy użyciu standardowego polecenia ping. –

+0

Sprawdź plik java.policy i inne ustawienia zabezpieczeń, prawdopodobnie w katalogu lib/security twojego domu Java. – crowne

+1

Jakie uprawnienia/konfiguracje szukam? I do czego to zmienię? –

2

Trochę za późno, ale natknąłem się na to, próbując zrobić to samo.

Jednym z obejść, który zadziałał dla mnie i którego użyłem, było użycie bezpośrednio wiersza poleceń.

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

Przetestowałem tę metodę w systemie Windows Server 2008 R2, a polecenie ping zwraca 0 w przypadku, gdy jest w stanie dotrzeć do hosta, aw przypadku, gdy nie jest, dlatego prawdopodobnie strumień wyjściowy musi zostać przeanalizowany, a nie polegać na powrocie – Irfan

1

Jednym z powodów jest to, że określony przez ciebie limit czasu jest zbyt niski. Miałem podobny problem, ale kiedy zwiększyłem limit czasu do odpowiedniej wartości, wywołanie isReachable zwróciło poprawną wartość.

8

Używam tej funkcji (od this article), kiedy potrzebuję prawdziwego ping ICMP w systemach Windows, Linux i OSX (nie testowałem innych systemów).

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

Link do "tego artykułu" jest martwy –

+0

Link działa dla mnie –

+0

Dziwne Kiedy kliknę link, prowadzi mnie do strony nie znaleziono –

1

Widziałem wiele złych kodów napisanych związanych z tym problemem.Kod, który pracował dla moich IS (strona nie wiem, aby poprawnie analizować mój plik kodu):

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

Dla łatwego ping z java bez przywilejów, używam http://www.icmp4j.org

Jest bardzo łatwy w użyciu:

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

Link do potencjalnego rozwiązania jest zawsze mile widziany, ale proszę [dodaj kontekst związany z linkiem] (http://meta.stackoverflow.com/a/8259/169503), aby inni użytkownicy mieli pewne pojęcie o tym, co to jest i dlaczego jest tutaj. Zawsze podawaj najważniejszą część ważnego linku, na wypadek, gdyby strona docelowa była nieosiągalna lub stała w trybie offline. Weź pod uwagę, że bycie "stanowiącym coś więcej niż link do zewnętrznej strony" jest możliwym powodem [dlaczego i jak niektóre odpowiedzi zostały usunięte?] (Http://stackoverflow.com/help/deleted-answers). – Tunaki

0

Stosując to nie pomoże w przypadku ping publiczne adresy IP za pomocą komputera z systemem Windows:

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

Uwaga: Dokumentacja stwierdza:

Typowa implementacja użyje żądań ICMP Echo jeśli przywilej można uzyskać w inny sposób będzie starał się nawiązać połączenie TCP na porcie 7 (Echo) docelowego hosta.

Próbowałem, ale wyniki nie były dokładne.

Co naprawdę dla mnie wyszło, to klasa napisana przez naszego kolegę użytkownika, który wysyła prawdziwy ICMP ping i zwraca wartość true lub false zgodnie ze statusem IP.

Odd InetAddress.isReachable() issue

Powiązane problemy