Java 如何快速检查URL服务器是否可用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25805580/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 01:12:20  来源:igfitidea点击:

How to quickly check if URL server is available

javaandroidhttpurl-validation

提问by AndreaF

I have a URL in the form

我在表单中有一个 URL

http://www.mywebsite.com/util/conv?a=1&from=%s&to=%s

And want to check if it is available.

并想检查它是否可用。

The links redirect me on a bad request page if I try to open these with a browser, however via code I can get the data that I need.

如果我尝试使用浏览器打开这些链接,这些链接会将我重定向到错误的请求页面,但是通过代码我可以获得我需要的数据。

Using a try-catch block on a HTTP request procedure is pretty slow, so I'm wondering how I could ping a similar address to check if its server is active.

在 HTTP 请求过程中使用 try-catch 块非常慢,所以我想知道如何 ping 一个类似的地址来检查它的服务器是否处于活动状态。



I have tried

我试过了

boolean reachable = InetAddress.getByName(myLink).isReachable(6000);

But returns always false.

但总是返回false

I have also tried

我也试过

public static boolean exists(String URLName) {

    try {
        HttpURLConnection.setFollowRedirects(false);
        HttpURLConnection con = (HttpURLConnection) new URL(URLName).openConnection();
        con.setConnectTimeout(1000);
        con.setReadTimeout(1000);
        con.setRequestMethod("HEAD");
        return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

That returns the correct value at the end of the process, bit is too slow if server is not available.

在过程结束时返回正确的值,如果服务器不可用,位太慢。

EDIT

编辑

I have understood what is the cause of slowness

我已经明白缓慢的原因是什么

a) if server returns some data but interrupts the request before complete the request the timeout is ignored and stuck until returns an Exceptionthat lead the execution to reach the catch block, this is the cause of the slowness of this method, and still I haven't found a valid solution to avoid this.

a)如果服务器返回一些数据但在完成请求之前中断请求,超时将被忽略并卡住,直到返回Exception导致执行到达catch块的一个,这是该方法缓慢的原因,但我仍然没有' t 找到了一个有效的解决方案来避免这种情况。

b) If I start the android device and open the App without connection, the false value is returned correctly, if the app is opened with internet connection active and the device lost its internet connection happens the same thing of the case A (also if I try to terminate and restart the App... I don't know why, I suppose that something remains cached)

b) 如果我启动 android 设备并在没有连接的情况下打开应用程序,则错误值将正确返回,如果应用程序在互联网连接活动的情况下打开并且设备失去互联网连接发生与情况 A 相同的事情(如果我尝试终止并重新启动应用程序......我不知道为什么,我想有些东西仍然被缓存)

All this seems related to the fact Java URLConnectiondoesn't provide no fail-safe timeout on reads. Looking at the sample at this linkI have seen that uses a thread to interrupt the connection in some way but if I add simply the line new Thread(new InterruptThread(Thread.currentThread(), con)).start();like in the sample nothing changes.

所有这一切似乎都与Java URLConnection没有提供读取时没有故障安全超时的事实有关。查看此链接中的示例,我看到它使用线程以某种方式中断连接,但是如果我new Thread(new InterruptThread(Thread.currentThread(), con)).start();像示例中那样简单地添加行,则没有任何变化。

回答by BSavaliya

public static boolean exists(String URLName) {

        try {
            HttpURLConnection.setFollowRedirects(false);
            // note : you may also need
            // HttpURLConnection.setInstanceFollowRedirects(false)
            HttpURLConnection con = (HttpURLConnection) new URL(URLName)
            .openConnection();
            con.setRequestMethod("HEAD");
            return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

回答by eridal

have you tried using raw sockets?

您是否尝试过使用原始套接字?

It should run faster as it's on a lower layer

它应该运行得更快,因为它在较低的层上

static boolean exists(String serverUrl)  {

    final Socket socket;

    try {
        URL url = new URL(serverUrl);
        socket = new Socket(url.getHost(), url.getPort());
    } catch (IOException e) {
        return false;
    }

    try {
        socket.close();
    } catch (IOException e) {
        // will never happen, it's thread-safe
    }

    return true;
}

回答by Sagar Pilkhwal

static public boolean isServerReachable(Context context) {
    ConnectivityManager connMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = connMan.getActiveNetworkInfo();
    if (netInfo != null && netInfo.isConnected()) {
        try {
            URL urlServer = new URL("your server url");
            HttpURLConnection urlConn = (HttpURLConnection) urlServer.openConnection();
            urlConn.setConnectTimeout(3000); //<- 3Seconds Timeout 
            urlConn.connect();
            if (urlConn.getResponseCode() == 200) {
                return true;
            } else {
                return false;
            }
        } catch (MalformedURLException e1) {
            return false;
        } catch (IOException e) {
            return false;
        }
    }
    return false;
}

or by using runtime:

或使用运行时:

Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("ping www.serverURL.com"); //<- Try ping -c 1 www.serverURL.com
int mPingResult = proc .waitFor();
if(mPingResult == 0){
    return true;
}else{
    return false;
}

You can try isReachable()but there is a bug filed for itand this comment says that isReachable() requires root permission:

您可以尝试,isReachable()但有一个错误为它归档此评论说 isReachable() 需要 root 权限

try {
    InetAddress.getByName("your server url").isReachable(2000); //Replace with your name
    return true;
} catch (Exception e)
{
    return false;
}

回答by Ironluca

As mentioned by 'eridal', that should be faster, open the socket; however, it only tells you that a server is listening on the host and port but to be sure, you need to write HTTP or alternately a bad request (junk), you should get HTTP/1.1 400 Bad Request. By reading the first line returned, if it contains HTTP, then you are sure that the server is a HTTP server. This way you are sure that the server is available as well as a HTTP server.

正如'eridal'所提到的,那应该更快,打开套接字;但是,它只告诉您服务器正在侦听主机和端口,但可以肯定的是,您需要编写 HTTP 或错误的请求(垃圾),您应该得到 HTTP/1.1 400 错误请求。通过读取返回的第一行,如果它包含 HTTP,那么您可以确定该服务器是一个 HTTP 服务器。这样您就可以确保服务器和 HTTP 服务器都可用。

This is in extension to the above answer by eridal.

这是 eridal 对上述答案的扩展。

回答by A_rmas

I had similar problem last month and someone helped me out with an optional example. I'd like to suggest you the same

上个月我遇到了类似的问题,有人用一个可选的例子帮助了我。我想给你同样的建议

public boolean isServerReachable()
    // To check if server is reachable
    {
        try {
            InetAddress.getByName("google.com").isReachable(3000); //Replace with your name
            return true;
        } catch (Exception e) {
            return false;
        }
    }

if return true than your url server is available else is not available currently.

如果返回 true 则您的 url 服务器可用,否则当前不可用。

回答by HuongNV

if (android.os.Build.VERSION.SDK_INT > 9) {
                            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
                                    .permitAll().build();

                            StrictMode.setThreadPolicy(policy);
                        }
                        try {
                            URL diachi = new URL("http://example.com");
                            HttpURLConnection huc = (HttpURLConnection) diachi.openConnection();
                            huc.setRequestMethod("HEAD");
                            int responseCode = huc.getResponseCode();

                            if (responseCode != 404) {
                                //URL Exist

                            } else {
                                //URL not Exist
                            }
                        } catch (MalformedURLException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

回答by khajappa

Below code waits until webpage is available:

下面的代码等待网页可用:

public void waitForWebavailability() throws Exception {
        boolean success = false;
        long waitTime = 0;
        while (!success) {
            try {
                waitTest(30000);
                waitTime += 30000;
                if (waitTime > 600000) {

                    System.out.println("Web page is not available");
                }
                webDriver.get("http://www.google.com");
                if (webDriver.getTitle().toLowerCase().contains("sometitle")) {
                    success = true;
                }
            } catch (Exception e) {
                success = false;
            }

        }

    }

// Code related to waittest

public void waitTest(long millis) throws Exception {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            throw new Exception(e);
        }
    }

回答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;
}

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

我不能只是 ping 我自己的页面,无论如何我都想请求它?当然!如果您想区分“互联网连接可用”和您自己的服务器可访问,您甚至可以同时检查两者

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.

它们有点不同,但在仅检查互联网连接的功能中,由于连接变量,第一种方法可能会变慢。