Java обнаруживает потерянное соединение
Когда я использую, например, PuTTY и мое соединение теряется (или когда я делаю руководство ipconfig /release
в Windows), он отвечает напрямую и уведомляет, что мое соединение было потеряно.
Я хочу создать программу Java, которая контролирует мое подключение к Интернету (на какой-то надежный сервер), чтобы регистрировать дату/время, когда мой интернет терпит неудачу.
Я попытался использовать метод Socket.isConnected()
, но навсегда вернет "true". Как это сделать в Java?
Ответы
Ответ 1
Хорошо, лучший способ узнать, прерывается ли ваше соединение, - попытаться прочитать/записать из сокета. Если операция завершилась неудачно, вы потеряли соединение когда-нибудь.
Итак, все, что вам нужно сделать, это попытаться прочитать с некоторым интервалом, и если сбой чтения не попытается повторно подключиться.
Важные события для вас будут, когда сбой чтения - вы потеряли соединение, а когда подключен новый сокет, вы восстановили соединение.
Таким образом, вы можете отслеживать время и время простоя.
Ответ 2
Несмотря на то, что протокол TCP/IP является "ориентированным на соединение", как правило, никакие данные не отправляются по незанятому соединению. Вы можете открыть сокет в течение года без одного бита, переданного по нему IP-стеком. Чтобы заметить, что соединение потеряно, вам необходимо отправить некоторые данные на уровне приложения. (*) Вы можете попробовать это, отключив телефонный кабель от вашего ADSL-модема. Все подключения на вашем ПК должны оставаться на месте, если только приложения не имеют какого-либо механизма keepalive на уровне приложений.
Таким образом, единственный способ заметить потерянное соединение - открыть TCP-соединение с некоторым сервером и прочитать некоторые данные из него. Возможно, самым простым способом может быть подключение к некоторому FTP-серверу и выборка небольшого файла - или списка каталогов - время от времени. Я никогда не видел общий сервер, который действительно предназначался для использования в этом случае, и владельцам FTP-сервера могут не нравиться клиенты, делающие это.
(*) Существует также механизм, называемый TCP keepalive, но во многих ОС вы должны активировать его для всех приложений, и это не очень удобно использовать, если вы хотите быстро заметить потерю соединения.
Ответ 3
Почему бы не использовать метод isReachable()
класса java.net.InetAddress
?
Как это работает, это конкретная реализация JVM, но:
Типичная реализация будет использовать ICMP ECHO REQUESTs, если эта привилегия может быть получена, в противном случае она попытается установить TCP-соединение на порте 7 (Echo) целевого хоста.
Если вы хотите постоянно открывать соединение, чтобы вы могли видеть, когда это не удается, вы можете скорее подключиться к серверу, на котором выполняется
Ответ 4
Если клиент правильно отсоединился, a read()
вернет -1, readLine()
возвращает null, readXXX()
для любых других бросков X EOFException
. Единственным надежным способом обнаружения потерянного TCP-соединения является запись на него. В конце концов, таким образом, будет выведено IOException
'соединение reset', но из-за буферизации требуется не менее двух записей.
Ответ 5
Возможно, вы захотите посмотреть на сокет интервал времени ожидания. С небольшим таймаутом (я считаю, что по умолчанию это "бесконечный тайм-аут" ), тогда вы можете уловить исключение или что-то, когда хост станет недоступным.
Ответ 6
Хорошо, поэтому я, наконец, начал работать с
try
{
Socket s = new Socket("stackoverflow.com",80);
DataOutputStream os = new DataOutputStream(s.getOutputStream());
DataInputStream is = new DataInputStream(s.getInputStream());
while (true)
{
os.writeBytes("GET /index.html HTTP/1.0\n\n");
is.available();
Thread.sleep(1000);
}
}
catch (IOException e)
{
System.out.println("connection probably lost");
e.printStackTrace();
}
Не так чисто, как я надеялся, но он не работает, если я не укажу os.writeBytes().
Ответ 7
Метод isConnected()
внутри класса Socket.java немного вводит в заблуждение. Он не говорит вам, подключен ли сокет к удаленному хосту (например, если он не закрыт). Вместо этого он сообщает вам, был ли сокет когда-либо подключен к удаленному хосту. Если сокет смог подключиться к удаленному хосту вообще, этот метод возвращает true
, даже после того, как этот сокет был закрыт. Чтобы узнать, открыт ли сокет, вам нужно проверить, что isConnected()
возвращает true
и isClosed()
возвращает false
.
Например:
boolean connected = socket.isConnected() && !socket.isClosed();
Ответ 8
Вы можете пинговать машину каждые несколько секунд, и это было бы довольно точно. Будьте осторожны, чтобы вы не сделали DOS.
Другой альтернативой будет запуск небольшого сервера на удаленном компьютере и сохранение связи с ним.
Ответ 9
Возможно, проще подключиться к yahoo/google или где-то в этом роде.
URL yahoo = new URL("http://www.yahoo.com/");
URLConnection yc = yahoo.openConnection();
int dataLen = yc.getContentLength() ;
Neil