Как быстро проверить, доступен ли сервер URL-адресов

У меня есть URL-адрес в форме

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

И хочу проверить, доступно ли это.

Ссылки перенаправляют меня на страницу с плохим запросом, если я пытаюсь открыть их с помощью браузера, однако через код я могу получить нужные мне данные.

Использование блока try-catch в процедуре HTTP-запроса выполняется довольно медленно, поэтому мне интересно, как я могу выполнить ping-адрес, чтобы проверить, активен ли его сервер.


Я пробовал

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

Но возвращается всегда false.

Я также пробовал

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

Это возвращает правильное значение в конце процесса, бит слишком медленный, если сервер недоступен.

ИЗМЕНИТЬ

Я понял, в чем причина медленности

a) если сервер возвращает некоторые данные, но прерывает запрос до завершения запроса, тайм-аут игнорируется и застревает до тех пор, пока не вернет Exception, который приведет выполнение к достижению блока catch, это является причиной медленности этого метода, и все же я не нашел правильного решения, чтобы избежать этого.

b) Если я запустил устройство Android и откройте приложение без подключения, ложное значение вернется правильно, если приложение открыто с подключением к Интернету активно, а устройство потеряло интернет-соединение, происходит то же самое в случае A ( также, если я пытаюсь закончить и перезапустить приложение... Я не знаю, почему, я полагаю, что что-то остается в кеше)

Все это, по-видимому, связано с тем, что Java URLConnection не обеспечивает отказоустойчивого таймаута при чтении. Глядя на образец на эту ссылку, я видел, что использует поток, чтобы каким-то образом прервать соединение, но если я просто добавлю строку new Thread(new InterruptThread(Thread.currentThread(), con)).start();, как в примере, ничего изменения.

Ответ 1

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

или используя время выполнения:

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

Вы можете попробовать isReachable(), но есть ошибка, зарегистрированная для него и этот комментарий говорит, что isReachable() требует прав на root:

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

Ответ 2

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

Ответ 3

Вы пытались использовать сырые сокеты?

Он должен работать быстрее, как на нижнем уровне

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 thread-safe
    }

    return true;
}

Ответ 4

Как упоминалось "eridal", это должно быть быстрее, откройте сокет; однако он сообщает только, что сервер прослушивает хост и порт, но, конечно, вам нужно написать HTTP или, альтернативно, плохой запрос (хлам), вы должны получить HTTP/1.1 400 Bad Request. Прочитав первую строку, если она содержит HTTP, вы уверены, что сервер является HTTP-сервером. Таким образом, вы уверены, что сервер доступен, а также HTTP-сервер.

Это добавление к вышеуказанному ответу eridal.

Ответ 5

Попробуйте этот код

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

Ответ 6

Ниже кода ждет пока доступна веб-страница:

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

Ответ 7

здесь автор предлагает следующее:

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

Не могу я просто пинговать свою собственную страницу, которую я хочу запросить в любом случае? Конечно! Вы даже можете проверить оба варианта, если вы хотите различать "доступное интернет-соединение" и ваши собственные серверы достижимы

прочитайте ссылку. его кажется очень хорошим

EDIT: в моем опыте использования, это не так быстро, как этот метод:

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

они немного разные, но в функциональности только для проверки подключения к Интернету первый способ может стать медленным из-за переменных соединения.

Ответ 8

У меня была аналогичная проблема в прошлом месяце, и кто-то помог мне с дополнительным примером. Я хотел бы предложить вам тот же

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

если return true, чем доступен ваш сервер url, в настоящее время недоступно.

Ответ 9

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