java http url ping

Forma preferida de Java para hacer ping a una URL HTTP para conocer la disponibilidad



(7)

Necesito una clase de monitor que compruebe regularmente si hay una URL HTTP dada disponible. Puedo ocuparme de la parte "regularmente" usando la abstracción Spring TaskExecutor, así que ese no es el tema aquí. La pregunta es: ¿Cuál es la forma preferida de hacer ping a una URL en Java?

Aquí está mi código actual como punto de partida:

try { final URLConnection connection = new URL(url).openConnection(); connection.connect(); LOG.info("Service " + url + " available, yeah!"); available = true; } catch (final MalformedURLException e) { throw new IllegalStateException("Bad URL: " + url, e); } catch (final IOException e) { LOG.info("Service " + url + " unavailable, oh no!", e); available = false; }

  1. ¿Es esto bueno para nada? ¿Hará lo que yo quiero?
  2. ¿Tengo que cerrar de alguna manera la conexión?
  3. Supongo que esta es una solicitud GET . ¿Hay alguna manera de enviar HEAD lugar?

¿Es esto bueno para nada? ¿Hará lo que yo quiero?

Puedes hacerlo. Otra forma viable es usar java.net.Socket .

public static boolean pingHost(String host, int port, int timeout) { try (Socket socket = new Socket()) { socket.connect(new InetSocketAddress(host, port), timeout); return true; } catch (IOException e) { return false; // Either timeout or unreachable or failed DNS lookup. } }

También está el InetAddress#isReachable() :

boolean reachable = InetAddress.getByName(hostname).isReachable();

Sin embargo, esto no prueba explícitamente el puerto 80. Se corre el riesgo de obtener falsos negativos debido a que un Firewall bloquea otros puertos.

¿Tengo que cerrar de alguna manera la conexión?

No, no lo necesitas explícitamente. Se maneja y se agrupa bajo las capuchas.

Supongo que esta es una solicitud GET. ¿Hay alguna manera de enviar HEAD en su lugar?

Puede convertir el URLConnection obtenido en HttpURLConnection y luego usar setRequestMethod() para establecer el método de solicitud. Sin embargo, debe tener en cuenta que algunos webapps deficientes o servidores locales pueden devolver un error HTTP 405 para un HEAD (es decir, no disponible, no implementado, no permitido) mientras que un GET funciona perfectamente bien. Usar GET es más confiable en caso de que pretenda verificar enlaces / recursos, no dominios / hosts.

Probar la disponibilidad del servidor no es suficiente en mi caso, necesito probar la URL (la aplicación web no se puede implementar)

De hecho, la conexión de un host solo informa si el host está disponible, no si el contenido está disponible. Puede suceder que un servidor web haya comenzado sin problemas, pero la aplicación web no se implementó durante el inicio del servidor. Sin embargo, esto no hará que todo el servidor baje. Puede determinarlo comprobando si el código de respuesta HTTP es 200.

HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("HEAD"); int responseCode = connection.getResponseCode(); if (responseCode != 200) { // Not OK. } // < 100 is undetermined. // 1nn is informal (shouldn''t happen on a GET/HEAD) // 2nn is success // 3nn is redirect // 4nn is client error // 5nn is server error

Para obtener más detalles sobre los códigos de estado de respuesta, consulte RFC 2616, sección 10 . Llamar a connect() por cierto no es necesario si está determinando los datos de respuesta. Se conectará implícitamente.

Para referencia futura, aquí hay un ejemplo completo en el sabor de un método de utilidad, también teniendo en cuenta los tiempos de espera:

/** * Pings a HTTP URL. This effectively sends a HEAD request and returns <code>true</code> if the response code is in * the 200-399 range. * @param url The HTTP URL to be pinged. * @param timeout The timeout in millis for both the connection timeout and the response read timeout. Note that * the total timeout is effectively two times the given timeout. * @return <code>true</code> if the given HTTP URL has returned response code 200-399 on a HEAD request within the * given timeout, otherwise <code>false</code>. */ public static boolean pingURL(String url, int timeout) { url = url.replaceFirst("^https", "http"); // Otherwise an exception may be thrown on invalid SSL certificates. try { HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setConnectTimeout(timeout); connection.setReadTimeout(timeout); connection.setRequestMethod("HEAD"); int responseCode = connection.getResponseCode(); return (200 <= responseCode && responseCode <= 399); } catch (IOException exception) { return false; } }


Considere usar el marco de Restlet, que tiene una gran semántica para este tipo de cosas. Es poderoso y flexible.

El código podría ser tan simple como:

Client client = new Client(Protocol.HTTP); Response response = client.get(url); if (response.getStatus().isError()) { // uh oh! }


El siguiente código realiza una solicitud HEAD para verificar si el sitio web está disponible o no.

public static boolean isReachable(String targetUrl) throws IOException { HttpURLConnection httpUrlConnection = (HttpURLConnection) new URL( targetUrl).openConnection(); httpUrlConnection.setRequestMethod("HEAD"); try { int responseCode = httpUrlConnection.getResponseCode(); return responseCode == HttpURLConnection.HTTP_OK; } catch (UnknownHostException noInternetConnection) { return false; } }


En lugar de utilizar URLConnection, use HttpURLConnection llamando a openConnection () en su objeto URL.

Luego use getResponseCode() le dará la respuesta HTTP una vez que haya leído de la conexión.

aquí está el código:

HttpURLConnection connection = null; try { URL u = new URL("http://www.google.com/"); connection = (HttpURLConnection) u.openConnection(); connection.setRequestMethod("HEAD"); int code = connection.getResponseCode(); System.out.println("" + code); // You can determine on HTTP return code received. 200 is success. } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (connection != null) { connection.disconnect(); } }

También verifique una pregunta similar ¿ Cómo verificar si existe una URL o devuelve 404 con Java?

Espero que esto ayude.


También puede usar HttpURLConnection , que le permite establecer el método de solicitud (por ejemplo, a HEAD). Aquí hay un ejemplo que muestra cómo enviar una solicitud, leer la respuesta y desconectarse.


wrt 2 .: será mejor que lo cierres. Sin embargo, puede depender de la implementación particular de URLConnection que se utiliza. Acabo de encontrar una fuga de recursos en nuestro sistema solo por eso. Una aplicación generó muchas conexiones colgantes (de acuerdo con lsof; la estamos ejecutando en JDK1.6) y la razón fue que hemos utilizado exactamente la parte del código que ha mostrado. Las conexiones TCP no se cerraron, por ejemplo, no se devolvieron al grupo, etc., se dejaron en estado ESTABLECIDO. En este caso, el escenario adecuado es el mostrado por YoK - echálo en (HttpURLConnection) e invoque .disconnect ().


here el escritor sugiere esto:

public boolean isOnline() { Runtime runtime = Runtime.getRuntime(); try { Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8"); int exitValue = ipProcess.waitFor(); return (exitValue == 0); } catch (IOException | InterruptedException e) { e.printStackTrace(); } return false; }

Posibles preguntas

  • ¿Es esto realmente rápido? Sí, ¡muy rápido!
  • ¿No podría simplemente hacer ping a mi propia página, que deseo solicitar de todos modos? ¡Por supuesto! Incluso podría verificar ambos, si desea diferenciar entre "conexión a internet disponible" y sus propios servidores accesibles. ¿Qué sucede si el DNS está inactivo? Google DNS (por ejemplo, 8.8.8.8) es el servicio de DNS público más grande del mundo. A partir de 2013 atiende 130 mil millones de solicitudes por día. Digamos que su aplicación no responde probablemente no sea la comidilla del día.

lee el enlace. parece muy bueno

EDITAR: en mi exp de usarlo, no es tan rápido como este método:

public boolean isOnline() { NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo(); return netInfo != null && netInfo.isConnectedOrConnecting(); }

son un poco diferentes, pero en la funcionalidad para simplemente verificar la conexión a Internet, el primer método puede volverse lento debido a las variables de conexión.