2010-03-15 16 views
28

Tengo un dispositivo en una red que estoy intentando hacer ping a través de mi programa Java. A través de mi símbolo del sistema de Windows, puedo hacer ping a la dirección del dispositivo y hacer un tracert en la dirección correcta.¿Cómo hacer un verdadero ping de Java desde Windows?

en línea, he visto que con el fin de hacer un ping a través de Java que tiene que hacer lo siguiente:

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

embargo, cuando se utiliza este código en mi dirección del dispositivo, siempre devuelve falsa en mi programa. Estoy usando la dirección IPv4 correcta con un buen valor de tiempo de espera. Además, si uso una dirección de host local, funciona bien.

¿Por qué puedo hacer ping al dispositivo a través de cmd, pero no a través de mi programa? He escuchado en varios lugares que esto no es verdadero ping.

¿Existe alguna forma mejor de emular un ping en Java?

Gracias

Respuesta

27

isReachable() utilizarán ICMP ECHO REQUEST s si el privilegio se puede obtener, de lo contrario se tratará de establecer una conexión TCP en el puerto 7 (Echo) del host de destino.
Por lo tanto, su problema probablemente sea un problema de configuración de permisos insuficientes para hacer esto en la máquina cliente o un problema de puerto 7 en el servidor si su cliente no tiene permiso para hacer el ICMP ECHO REQUEST. Probablemente ambos en tu caso, necesites resolver uno u otro lado para que esto funcione.

He probado lo siguiente en clientes OSX y Linux, y funciona al probar la posibilidad de acceso de otras máquinas OSX, Linux y Windows Server. No tengo una máquina con Windows para ejecutar esto como cliente.

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

por lo que leí here. Aparentemente es una limitación de Windows y ICMP PING no es compatible con Windows como una llamada al sistema anterior a Windows 2000, por lo que se usa de forma predeterminada para conectarse al puerto 7 y está bloqueado en la máquina que está tratando de "alcanzar". Java aún no es compatible con la nueva llamada al sistema nativo. Los permisos están relacionados con el sistema basado en Unix, ya que requieren que root envíe paquetes ICMP.

Si desea rodar su propio Windows nativo JNIICMP PING para Windows 2000 y posterior existe el IcmpSendEcho Function.

+1

... pero puedo hacerlo a través de comandos de Windows utilizando el comando ping estándar. –

+0

Revise su archivo java.policy y otras configuraciones de seguridad, probablemente bajo el directorio lib/security de su hogar java. – crowne

+1

¿Qué permisos/configuraciones estoy buscando? ¿Y a qué lo cambio? –

2

Un poco tarde, pero me encontré con esto al intentar hacer lo mismo.

Una solución que funcionó para mí y que utilicé fue simplemente usar el comando de línea de comando ping directamente.

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

He probado este método en Windows Server 2008 R2 y de ping devuelve 0 en caso de que sea capaz de alcanzar el host y en caso de que no se lo tanto, tal vez el flujo de salida tiene que ser analizado en lugar de confiar en la declaración. valor – Irfan

1

Una de las razones es que el tiempo de espera que ha especificado es demasiado bajo. Tuve un problema similar pero cuando aumenté el tiempo de espera a un valor apropiado, la invocación de isReachable devolvió un valor correcto.

8

Utilizo esta función (desde this article) cuando necesito un ping ICMP real en Windows, Linux y OSX (no he probado otros sistemas).

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

El enlace de "este artículo" está muerto –

+0

El vínculo funciona para mí –

+0

Extraño. Cuando hago clic en el enlace, me lleva a una página no encontrada. –

1

Vi un montón de código incorrecto escrito relacionado con ese tema.El código que trabajó para mi es (sitio no saben analizar correctamente mi archivo de código):

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

Para una mesa de ping fácil de java sin privilegios, yo uso http://www.icmp4j.org

Es muy fácil de usar:

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

Un enlace a una solución potencial siempre es bienvenido, pero por favor [agregue contexto alrededor del enlace] (http://meta.stackoverflow.com/a/8259/169503) para que los demás usuarios tengan una idea de qué es y por qué está allá. Siempre cite la parte más relevante de un enlace importante, en caso de que el sitio objetivo no esté disponible o esté permanentemente fuera de línea. Tenga en cuenta que ser apenas más que un enlace a un sitio externo es una posible razón para [¿Por qué y cómo se eliminan algunas respuestas?] (Http://stackoverflow.com/help/deleted-answers). – Tunaki

0

usando esta no va a ayudar en caso de una mesa de ping direcciones IP públicas utilizando máquina de Windows:

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

Nota: La documentación indica que:

Una aplicación típica utilizará peticiones de eco ICMP si se puede obtener el privilegio , de lo contrario se tratará de establecer una conexión TCP en el puerto 7 (Echo) del host de destino.

Lo he intentado pero los resultados no eran precisos.

Lo que realmente funcionó para mí es la clase escrito por nuestro compañero de usuario que envía cierto ping ICMP y devuelve verdadero o falso según el estado de IP.

Odd InetAddress.isReachable() issue

Cuestiones relacionadas