El Bazar

Todo | Linux | General | Java
« Nada | Main | UE 1 - Microsoft 0... »

20040316 Tuesday March 16, 2004

El dichoso Ping en Java

¿Qué informático no ha ejecutado nunca el siguiente comando?

C:\>ping www.yahoo.es

Haciendo ping a www.euro.yahoo.akadns.net [217.12.3.11] con 32 bytes de datos:

Respuesta desde 217.12.3.11: bytes=32 tiempo=202ms TTL=243
Respuesta desde 217.12.3.11: bytes=32 tiempo=317ms TTL=243
Respuesta desde 217.12.3.11: bytes=32 tiempo=235ms TTL=243
Respuesta desde 217.12.3.11: bytes=32 tiempo=258ms TTL=243

Estadísticas de ping para 217.12.3.11:
    Paquetes: enviados = 4, recibidos = 4, perdidos = 0
    (0% perdidos),
Tiempos aproximados de ida y vuelta en milisegundos:
    Mínimo = 202ms, Máximo = 317ms, Media = 253ms
Es tan común que parece extraño que incluso en la versión actual de Java 1.4.2 no exista ninguna función con ese cometido, pero es que además tampoco puede implementarla uno mismo programando sólo en Java. Por ambos motivos, por lo habitual y la falta de una solución, es tanto una de las preguntas más frecuentes que hacen los desarrolladores que se inician en Java, como una de las peticiones más demandadas a Sun, concretamente la número 4727550 ICMP protocol support a.k.a. PING applets pide que se pueda hacer un ping con código Java ya en Noviembre de 1997 (!hace más de 6 años!), teniendo con sus 254 votos un lugar destacado entre el top 25 de fallos y peticiones de mejoras sobre J2SE.

¿Por que tantos problemas por un simple ping? Pues porque no todo es tan sencillo como parece a primera vista, el asunto no se resuelve con una conexión normal tipo HTTP, sino que este comando excepcionalmente necesita de ICMP que es un protocolo de red de bajo nivel, utilizado por ejemplo para la monitorización de la red o el enrutado. Pero el acceso a ICMP se considera privilegiado ya que su mal uso puede comprometer la seguridad del sistema, por lo que sólo está disponible para el usuario root en Unix o el Administrador de Windows. Por ejemplo en Linux para resolver este inconveniente el comando ping ignora nuestra identidad actual y se ejecuta como root automáticamente, sin necesidad de preguntarnos una contraseña, esto es seguro porque el administrador nos concede estos permisos sólo durante el ping, que es un ejecutable en el que confía y que no puede ser modificado por otros usuarios salvo él mismo. Actualmente no existe ningún API en Java sobre el protocolo ICMP, eso queda pendiente para otra futura mejora ya con 65 votos, pero aunque fuese ese el caso difícilmente el usuario va a conceder alegremente permisos de root o Administrador a nuestros programas Java sólo porque le expliquemos que queremos hacer un ping, mucho menos si se trata de un applet o de una aplicación servidor.

¿Que podemos hacer entonces? La solución más fácil consiste en ejecutar el comando ping de nuestro sistema operativo utilizando la función Runtime.exec y comprobar el valor de retorno que nos dirá cuando el ordenador responde o no. Hay que tener en cuenta que los parámetros del comando ping y su funcionamiento varían ligeramente en Linux y Windows, además el sistema de seguridad de Java nos pedirá autorización si se trata de un applet o una aplicación con webstart, pero no será necesario que seamos ni root ni Administrador. Problema resuelto, no es 100% Java pero sí bastante portable.

A partir de J2SE 1.5 tenemos una opción más. La clase java.net.InetAddress tiene una nueva función public boolean isReachable(int timeout) que viene a ser más o menos como un ping. Esta función intenta determinar si puede establecer una conexión con un ordenador remoto, para ello en primer lugar cuando el usuario tenga los permisos de administrador necesarios enviará un ping, en caso contrario enviará un ECHO. ¿Que es un ECHO? Pues poca cosa, otro protocolo utilizado para determinar si un ordenador está activo o no, tiene la ventaja de que sí se trata de un protocolo normal sin restricciones de seguridad (puerto 7), pero el grandísimo inconveniente de que la mayoría de los ordenadores que sí responden al ping ignoran completamente el ECHO. En la práctica esto significa que si no tenemos esos permisos de administrador la función isReachable no va a poder establecer una conexión en la mayoría de los casos aunque tenga el otro ordenador perfectamente funcionando a dos palmos. Además me he encontrado que en la versión beta actual de J2SE 1.5 esta función en Windows produce una excepción si el usuario no es el Administrador, en vez de mandar ese ECHO como indica su contrato, cosas de betas supongo.

¿Es que no hay una solución mejor? La verdad es que sí, pero requiere plantearse el problema incial y preguntarse ¿para qué necesitamos enviar un ping? ¿que significa establecer una conexión? Por ejemplo quizás queramos descargar unas páginas web para el usuario, tenemos que tener en cuenta entonces que aunque el ordenador remoto nos responda al ping es posible que su servidor web no funcione o que sencillamente no tenga ninguno, además también es habitual encontrarse con servidores web que por seguridad no responden al ping. En este caso el ping no nos aporta la información que queremos, si el servidor web es o no accesible, en su lugar como mecanismo de comprobación es mucho mejor establecer una conexión HTTP habitual que sí nos dirá si el servidor web responde o no, además sin caer en las restricciones de seguridad del ping. La mayoría de las situaciones son muy similares, normalmente lo que queremos saber es si un servicio de un ordenador remoto está operativo, como el servidor web, un servicio XMP-RPC o cualquier otro, una conexión específica a ese servicio con su protocolo nos proprocionará una información más fiable que un simple ping. No es siempre así, en un caso me encontré con una aplicación J2EE que necesitaba comprobar si unos ordenadores estaban encendidos o no, un ping implementado con una llamada al comando del sistema operativo fue la solución en ese caso, pero sólo ha sido una vez entre muchas otras.

Así que la moraleja de esta historia es pensarse dos veces si necesitamos un ping o no, seguramente tendremos una mejor respuesta consultando el servicio que nos interesa, además con código 100% Java.

(2004-03-16 23:09:11.0) Permalink Comentarios [3]

URL de la referencia: http://weblogs.javahispano.org/jmrus/entry/el_dichoso_ping_en_java
Comentarios:

buen apuente !!

Enviado por kail2 en March 22, 2005 a las 07:27 PM CET #

Con el "java.net.InetAddress" si el host que piensas hacerle un Ping tiene un FireWare un poco mediano, no te deja hacer el Ping, aunqué desde el comando MS-DOS sí te deje jacerlo.

Ahora estoy invertigando, si encuentro algo ya lo diré.

Enviado por Sesperanto en April 04, 2006 a las 01:06 PM CEST #

Se puede realizar un comando ping con notacion binaria es decir ping 10100000.10000100.0000001.000001 y como puede hacerlo

Enviado por Rommel en July 08, 2006 a las 12:54 AM CEST #

Enviar un comentario:

Nombre:
Correo electrónico:
URL:

Su comentario:

Sintaxis HTML: Deshabilitado