Краткий ответ: да, вы должны закрыть сокет на обоих концах.
Несмотря на то, что ответ прост, в действительности может быть очень трудно обнаружить, что узел прекратил отвечать, если вы не встроите какую-либо схему ACK / NACK в свой протокол клиент-сервер.
Даже с ACK вашего протокола ваш поток обработки может зависать в ожидании ACK, которые никогда не поступят от клиента или наоборот.
Если вы используете блокировку ввода / вывода, я бы начал с установки таймаутов чтения в сокете. К сожалению, если одноранговый узел перестает отвечать на запросы, соответствующего времени ожидания для записи не существует.
Один тупой инструмент, который я нашел, имеет значение в нашей среде - это создание блокирующих сокетов с помощью методов java.nio, а затем прерывание потока обработки через настраиваемые интервалы.
Прерывание потока обработки закроет сокет, но если вы выберете достаточно большое время ожидания, вы будете знать, что возникла проблема. Мы выбрали этот подход, потому что приложение изначально было написано с блокирующим вводом-выводом, а стоимость перехода на неблокирующую систему была очень высокой.
Тем не менее, при неблокирующем вводе / выводе вы можете через более мелкий интервал проверять состояние вашего соединения и более разумно реагировать на медленные / не отвечающие соединения.
Несмотря на то, что неблокируемый ввод-вывод требует более высоких начальных инвестиций, я думаю, что в дальнейшем он принесет больше дивидендов с точки зрения надежности и большей пропускной способности.