Как идентифицировать разорванное сокетное соединение в Java сразу? - PullRequest
3 голосов
/ 04 ноября 2011

У меня есть типичный клиент Java и сервер. Клиент отправляет некоторый запрос на сервер и ждет ответа. Клиент считывает до 100 байтов данных из содержащегося входного потока в массив байтов. Он ожидает считывания полного ответа в 100 байтов в течение заданного периода времени, скажем, 3 секунды. Проблема здесь состоит в том, чтобы определить, вышел ли из строя сервер или произошел сбой во время / до написания ответа. По сути, нам нужно определить, был ли сокет сломан или по какой-либо причине отключен одноранговый узел. Есть ли способ определить это?

Ответы [ 4 ]

4 голосов
/ 04 ноября 2011

Как сразу определить разорванное сокетное соединение в Java?

Вы не можете обнаружить его сразу, на Java или любом другом языке.TCP / IP не знает, поэтому Java не может знать.Единственный надежный способ обнаружить разорванное TCP-соединение - записать его и перехватить исключения IOException, и они не произойдут немедленно.

2 голосов
/ 04 ноября 2011

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

Если у вас есть плавное отключение (например, вызовы другого конца close ()), чтение по соединению сообщит вам, когда буфер будет очищен.

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

РЕДАКТИРОВАТЬ: я не считаю хорошей идеей быть слишком агрессивным в автоматической обработке "сбоев" соединения / сервиса. Обычно это лучше обрабатывается запланированным исправлением системы, основанным на расследовании истинной причины. например увеличенная пропускная способность, избыточное подключение, более быстрые серверы, исправления кода.

1 голос
/ 04 ноября 2011

Если соединение оборвано ненормально, вы получите IOException при чтении;это обычно происходит довольно быстро, но нет никаких гарантий относительно времени - все зависит от ОС, сетевого оборудования и т. д. Если удаленный конец изящно закрывает сокет, вы будете читать -1 как следующий байт.

0 голосов
/ 03 января 2018

При условии, что все остальное работает, если удаленный узел - сервер TCP - был убит, тогда клиент TCP обычно получит TCP RST (сброс), и вы получите IOException в своем клиентском приложении.

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

Для вышеупомянутогоПричины, по которым общее правило - как указано в ответе EJP - что разорванное соединение может быть обнаружено только путем записи в него .Вот почему всегда рекомендуется, чтобы TCP-клиент и TCP-сервер обменивались сообщениями определенного типа с регулярными интервалами.Есть разные способы сделать это.Мне больше всего нравится метод, в котором TCP-клиент будет - при отсутствии данных, получаемых с TCP-сервера - отправлять сообщение пульса на сервер и ожидать ответа в течение определенного периода времени.Таким образом, сообщения сердцебиения будут отправляться только тогда, когда это действительно необходимо.

Неоптимальный подход - если вы не можете реализовать истинное сердцебиение - это всегда читать с таймаутом.Установите тайм-аут на сокете , а затем перехватите java.net.SocketTimeoutException.Это позволит вам знать, что в течение x миллисекунд не было получено никаких данных на сокете.

Следует отметить, что есть один сценарий, в котором вам не нужно использовать биение сердца или тайм-аут сокета: еслиTCP-клиент и TCP-сервер обмениваются данными по интерфейсу обратной связи, после чего разорванное соединение всегда будет передаваться как клиентскому приложению TCP, так и приложению сервера TCP.Это связано с тем, что в данном случае между двумя процессами нет сетевой инфраструктуры.Таким образом, если у вас есть существующее приложение, которое не разработано с точки зрения связи по протоколу TCP (т.е. оно не реализует какую-либо форму сердцебиения или, по крайней мере, чтения с тайм-аутом), то в качестве последнего средства вы можете «исправить»проблема заключается в перемещении двух приложений на один и тот же хост и разрешении их связи через интерфейс обратной связи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...