Как быстро проверить, доступен ли сервер 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();
}