ping HTTP URL 以确保可用性的首选 Java 方式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3584210/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Preferred Java way to ping an HTTP URL for availability
提问by Sean Patrick Floyd
I need a monitor class that regularly checks whether a given HTTP URL is available. I can take care of the "regularly" part using the Spring TaskExecutor abstraction, so that's not the topic here. The question is: What is the preferred way to ping a URL in java?
我需要一个监视器类来定期检查给定的 HTTP URL 是否可用。我可以使用 Spring TaskExecutor 抽象来处理“定期”部分,所以这不是这里的主题。问题是:在java中ping URL的首选方法是什么?
Here is my current code as a starting point:
这是我当前的代码作为起点:
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;
}
- Is this any good at all (will it do what I want)?
- Do I have to somehow close the connection?
- I suppose this is a
GET
request. Is there a way to sendHEAD
instead?
- 这有什么好处(它会做我想要的吗)?
- 我必须以某种方式关闭连接吗?
- 我想这是一个
GET
请求。有没有办法发送HEAD
?
采纳答案by BalusC
Is this any good at all (will it do what I want?)
这有什么好处吗(它会做我想要的吗?)
You can do so. Another feasible way is using java.net.Socket
.
你可以这样做。另一种可行的方法是使用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.
}
}
There's also the InetAddress#isReachable()
:
boolean reachable = InetAddress.getByName(hostname).isReachable();
This however doesn't explicitly test port 80. You risk to get false negatives due to a Firewall blocking other ports.
然而,这并没有明确测试端口 80。由于防火墙阻止了其他端口,您可能会得到漏报。
Do I have to somehow close the connection?
我必须以某种方式关闭连接吗?
No, you don't explicitly need. It's handled and pooled under the hoods.
不,你没有明确需要。它在引擎盖下处理和汇集。
I suppose this is a GET request. Is there a way to send HEAD instead?
我想这是一个 GET 请求。有没有办法发送 HEAD 呢?
You can cast the obtained URLConnection
to HttpURLConnection
and then use setRequestMethod()
to set the request method. However, you need to take into account that some poor webapps or homegrown servers may return HTTP 405 errorfor a HEAD (i.e. not available, not implemented, not allowed) while a GET works perfectly fine. Using GET is more reliable in case you intend to verify links/resources not domains/hosts.
您可以将获得的转换URLConnection
为HttpURLConnection
然后用于setRequestMethod()
设置请求方法。但是,您需要考虑到一些糟糕的 web 应用程序或本地服务器可能会为 HEAD返回HTTP 405 错误(即不可用、未实现、不允许),而 GET 工作得很好。如果您打算验证链接/资源而不是域/主机,则使用 GET 更可靠。
Testing the server for availability is not enough in my case, I need to test the URL (the webapp may not be deployed)
在我的情况下测试服务器的可用性是不够的,我需要测试 URL(可能未部署 webapp)
Indeed, connecting a host only informs if the host is available, not if the content is available. It can as good happen that a webserver has started without problems, but the webapp failed to deploy during server's start. This will however usually not cause the entire server to go down. You can determine that by checking if the HTTP response code is 200.
实际上,连接主机只会通知主机是否可用,而不是内容是否可用。Web 服务器启动时没有问题,但 Web 应用程序在服务器启动期间未能部署,这也可能是一件好事。然而,这通常不会导致整个服务器宕机。您可以通过检查 HTTP 响应代码是否为 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
For more detail about response status codes see RFC 2616 section 10. Calling connect()
is by the way not needed if you're determining the response data. It will implicitly connect.
有关响应状态代码的更多详细信息,请参阅RFC 2616 第 10 节。connect()
顺便说一下,如果您要确定响应数据,则不需要调用。它将隐式连接。
For future reference, here's a complete example in flavor of an utility method, also taking account with timeouts:
为了将来参考,这里有一个实用方法风格的完整示例,还考虑了超时:
/**
* 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;
}
}
回答by Bill the Lizard
You could also use HttpURLConnection, which allows you to set the request method (to HEAD for example). Here's an examplethat shows how to send a request, read the response, and disconnect.
您还可以使用HttpURLConnection,它允许您设置请求方法(例如 HEAD)。 这是一个示例,展示了如何发送请求、读取响应和断开连接。
回答by YoK
Instead of using URLConnection use HttpURLConnectionby calling openConnection() on your URL object.
通过在 URL 对象上调用 openConnection()来代替使用 URLConnection 使用HttpURLConnection。
Then use getResponseCode()will give you the HTTP response once you've read from the connection.
然后使用getResponseCode()将在您从连接中读取后为您提供 HTTP 响应。
here is code:
这是代码:
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();
}
}
Also check similar question How to check if a URL exists or returns 404 with Java?
还要检查类似的问题如何使用 Java 检查 URL 是否存在或返回 404?
Hope this helps.
希望这可以帮助。
回答by Avi Flax
Consider using the Restlet framework, which has great semantics for this sort of thing. It's powerful and flexible.
考虑使用 Restlet 框架,它对这类事情有很好的语义。它功能强大且灵活。
The code could be as simple as:
代码可以很简单:
Client client = new Client(Protocol.HTTP);
Response response = client.get(url);
if (response.getStatus().isError()) {
// uh oh!
}
回答by BullyWiiPlaza
The following code performs a HEAD
request to check whether the website is available or not.
以下代码执行HEAD
请求以检查网站是否可用。
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;
}
}
回答by Emad
herethe writer suggests this:
作者在这里建议:
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;
}
Possible Questions
可能的问题
- Is this really fast enough?Yes, very fast!
- Couldn't I just ping my own page, which I want to request anyways? Sure! You could even check both, if you want to differentiate between “internet connection available” and your own servers beeing reachable What if the DNS is down? Google DNS (e.g. 8.8.8.8) is the largest public DNS service in the world. As of 2013 it serves 130 billion requests a day. Let ‘s just say, your app not responding would probably not be the talk of the day.
- 这真的够快了吗?是的,非常快!
- 我不能只是 ping 我自己想要请求的页面吗?当然!如果您想区分“互联网连接可用”和您自己的服务器是否可访问,您甚至可以同时检查两者 如果 DNS 关闭怎么办?Google DNS(例如 8.8.8.8)是世界上最大的公共 DNS 服务。截至 2013 年,它每天处理 1300 亿个请求。只是说,您的应用程序没有响应可能不是今天的话题。
read the link. its seems very good
阅读链接。它看起来很好
EDIT: in my exp of using it, it's not as fast as this method:
编辑:在我使用它的经验中,它不如这种方法快:
public boolean isOnline() {
NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
return netInfo != null && netInfo.isConnectedOrConnecting();
}
they are a bit different but in the functionality for just checking the connection to internet the first method may become slow due to the connection variables.
它们有点不同,但在仅检查互联网连接的功能中,由于连接变量,第一种方法可能会变慢。