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

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

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

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

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

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


я пытался

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, это причина медлительности этого метода, и все же я не знаю не нашел подходящего решения, чтобы избежать этого.

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

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


person AndreaF    schedule 12.09.2014    source источник
comment
попробуйте использовать getResponseMessage () или getResponseCode ()   -  person KOTIOS    schedule 12.09.2014
comment
Плохой запрос означает, что ваш URL недействителен, но не то, что сервер недоступен.   -  person Alexander Zhak    schedule 12.09.2014
comment
@mtetno Не могли бы вы дать мне более подробную информацию о том, что пользователь ответил на что-то похожее, но кажется таким же медленным, как ожидание исключения связанного блока try catch   -  person AndreaF    schedule 12.09.2014
comment
Давайте обсудим в чате stackoverflow   -  person KOTIOS    schedule 13.09.2014
comment
@mtetno Я был оффлайн, когда вы написали комментарий. Если мы подключимся в разное время, возможно, начать чат будет непросто, почему вы не даете ответа? Я буду рад принять и проголосовать, если решу мою проблему, и, кроме того, если у кого-то есть такая же проблема, я могу найти полезную помощь. Спасибо   -  person AndreaF    schedule 13.09.2014
comment
см.   -  person Srinath Ganesh    schedule 21.09.2014


Ответы (7)


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;
}
person Sagar Pilkhwal    schedule 17.09.2014
comment
первый образец имеет ту же проблему с кодом, который я опубликовал (работает, но работает медленно, когда сервер не дает ответа), второй образец всегда возвращает false - person AndreaF; 18.09.2014
comment
я отредактировал свой ответ, попробуйте также ping -c 1 www.serverURL.com - person Sagar Pilkhwal; 19.09.2014
comment
Я добавил -1 c после ping, но всегда возвращаю false, несмотря на то, что первый метод по той же ссылке возвращает правильно true - person AndreaF; 19.09.2014
comment
ну, вы можете сослаться на этот SO Post, в котором использовался java.net.Socket - person Sagar Pilkhwal; 22.09.2014
comment
первый пример = ›java.net.MalformedURLException: Протокол не найден: www.google.com - person Zin Win Htet; 29.04.2016
comment
У меня сообщение об ошибке: android.os.NetworkOnMainThreadException - person ΩlostA; 19.03.2020

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

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

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;
}
person eridal    schedule 17.09.2014
comment
с этим кодом приложение вылетает и получает исключение порта вне диапазона - person AndreaF; 18.09.2014

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

Это продолжение вышеприведенного ответа от eridal.

person Ironluca    schedule 17.09.2014

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

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-сервер доступен, иначе в настоящее время недоступен.

person A_rmas    schedule 19.09.2014
comment
или вы можете проверить stackoverflow.com/questions/ 25541940 / - person A_rmas; 19.09.2014
comment
как я уже сказал в своем вопросе, этот код всегда возвращает false с моей ссылкой - person AndreaF; 20.09.2014
comment
По вашей ссылке вы перейдете по ссылке website.1and1.com/#top, поэтому пробуйте только с website.1and1.com. Возвращает истину - person A_rmas; 22.09.2014
comment
Ошибка сообщения android.os.NetworkOnMainThreadException. Не работает - person ΩlostA; 19.03.2020
comment
поэтому он вернул false, что означает, что сервер не может быть перепроверен. - person A_rmas; 22.03.2020

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

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);
        }
    }
person khajappa    schedule 07.01.2016

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

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

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

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

РЕДАКТИРОВАТЬ: в моем опыте использования это не так быстро, как этот метод:

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

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

person Emad    schedule 29.08.2017

person    schedule
comment
Этот код работает, но работает так же медленно, как и ожидание исключения блока try catch. - person AndreaF; 12.09.2014