Вопрос по java, sockets, outputstream, stream, inputstream – JAVA: Обработка разъединения розетки

0
Два компьютера соединены через сокет. Если сервер / клиент закрывает соединение со своего конца (т.е. закрывает,InputStreamOutputStream а такжеSocket) тогда как я могу сообщить другому концу о разъединении? Есть один способ, которым я знаю - пытаться читать сInputStream, который бросаетIOException если соединение закрыто, но есть ли другой способ обнаружить это?Другой вопрос, я посмотрел проблему в интернете и увиделinputStream.available() не решает эту проблему. Это почему?

Дополнительная информация: яЯ прошу другой путь, потому что мой проект становится трудно обрабатывать, если я пытаюсь читать изInputStrem обнаружить отключение.

Хм, не уверен, как еще вы ожидаете решить эту проблему. Вам все еще понадобится какой-нибудь сокет для чтения или записи, чтобы определить, что он был закрыт. Tudor
@SaintHill Allthat ничего не добавляет к чтению самостоятельно. user207421
@EJP Правда. Это'просто альтернативный способ сделать неизбежное :) The Coordinator
Подумав, как вы можете сделать это, чтобы они были мгновенным уведомлением, когда другая сторона закрывает (правильно закрывает, а не просто отключает) свой сокет: 1) Поток, предназначенный для чтения сокета и помещения данных в контейнер для будущей обработки, например , ArrayBlockingQueue. Когда он находит -1 или IOException, он может остановить и уведомить другие потоки о том, что обмен данными завершен (или был прерван), установив флаг, вызвав какой-либо метод или поместив маркер EOS в очередь. 2) Другие потоки могут читать очередь, когда они хотят, а также проверять флаг, когда они хотят. The Coordinator

Ваш Ответ

4   ответа
0

Q1 Если вы закроете сокетное соединение на сервере, клиент должен сгенерировать исключение, если не сразу, конечно, при следующей попытке чтения, и наоборот.

Q2 из JavaDocs

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

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

Socket.isClosed () не работаетне могу сказать вам, закрыл ли узел свой конец соединения. Он говорит вам, закрыли ли вы это гнездо. user207421
@EJP Спасибо за указатель MadProgrammer
Это только то же самое, если его бросают, и ни один из трехread() методы бросают это. user207421
Клиент выигралброситьIOException, Этоможет быть броситьEOFExceptionв зависимости от того, какой метод чтения он вызвал. user207421
@EJP СEOFException простирается отIOExceptionэто примерно одно и то же, в зависимости от того, какой уровень исключения вы хотите обработать. "может быть" часть это здорово знать MadProgrammer
6

пытается прочитать из InputStream, который выбрасывает IOException

Это не правильно. Если узел закрывает сокет:

  • read() возвращает -1
  • readLine() возвращает ноль
  • readXXX() бросаетEOFExceptionдля любого другого X.

КакInputStream только имеетread() методы, он возвращает только -1: он неброситьIOException в EOS.

Вопреки другим ответам здесь, нет TCP API или метода Socket, который бы сообщал вам, закрыл ли одноранговое соединение. Вы должны попробовать читать или писать.

Вы должны использовать тайм-аут чтения.

InputStream.available() Безразлично»не решить проблему, потому что это неt вернуть индикацию EOS любого вида. Есть несколько правильных применений, и это нет один из них.

0

Проблема не "если сервер / клиент закрывает соединение, Проблема в "Что делать, если они не закрывают соединение, а соединение разорвано? "

Нет способа обнаружить это без собственного протокола сердцебиения.

Другой вариант - установить для SO_KEEPALIVE значение true. "

Если для сокета TCP установлена опция keepalive, и в течение 2 часов между сокетами в обоих направлениях не было обмена никакими данными (ПРИМЕЧАНИЕ: фактическое значение зависит от реализации) "

По моему опыту, это гораздо раньше, чем каждые 2 часа. Больше похоже на ~ 5 минут. Кроме использования So_KEEPALIVE, вы по-королевски облажались: P

В моих протоколах связи я использую зарезервированныйстук сердца' байт, который отправляется каждые 2 секунды. Мои собственные filterInputStream и filterOutputStream отправляют / и переваривают байт пульса.

Нет, я понял, я смеялся над частью "ты по-королевски облажался: P " Jisan Mahmud
Человек, я смеялся над вашим ответом: D Jisan Mahmud
Установка SO_KEEPALIVE ничего не делает, если вы не выполняете чтение или запись, и если узел закрывает соединение, он вообще ничего не делает. Это'это не тест EOS, этоs способ обнаружения прерванных незанятых соединений. user207421
0

Нет способа O-O-O получить обратный вызов / исключение в момент разрыва соединения. О разорванном соединении вы узнаете только тогда, когда выполняете явное чтение / запись в потоке сокета.

Есть два способа чтения из сокета, а именно. Синхронно читаем побайтово по мере поступления; или подождите до желаемого количества байтов, доступных в потоке, а затем выполните массовое чтение. Вы делаете проверку, вызывая available () в потоке сокета, который дает вам количество байтов, доступных в данный момент для чтения. Во втором случае, если сокетное соединение по какой-то причине разорвано, вы не сможете получить уведомление об этом. В этом случае вам нужно использовать механизм ожидания для вашего ожидания. В первом случае, когда вы делаете явное чтение / запись, вы получаете исключение.

О-О-О не имеет к этому никакого отношения. Там нет никакого способа вообще. Техника звонкаavailable() не имеет ничего, чтобы рекомендовать это. Это'Это просто более сложный и более подверженный ошибкам способ блокировки в цикле. user207421

Похожие вопросы