Ключевое слово здесь (without closing the socket properly)
.
Сокеты всегда следует приобретать и утилизировать следующим образом:
final Socket socket = ...; // connect code
try
{
use( socket ); // use socket
}
finally
{
socket.close( ); // dispose
}
Даже с учетом этих мер предосторожности вы должны указать тайм-ауты приложения, относящиеся кваш протокол.
Мой опыт показал, что, к сожалению, вы не можете надежно использовать любую из функций тайм-аута Socket (например, нет времени ожидания для операций записи, и даже операции чтения могут иногда зависать).
Вот почему вам нужен сторожевой поток, который устанавливает таймауты вашего приложения и удаляет сокеты, которые некоторое время не отвечали.
Один удобный способ сделать это - инициализировать Socket и ServerSocket через соответствующие каналы в Java..nio.Основное преимущество таких сокетов состоит в том, что они являются прерываемыми, поэтому вы можете просто прервать поток, выполняющий протокол сокетов, и убедиться, что сокет правильно отключен.
Обратите внимание, что вы должны принудительно устанавливать таймауты приложений с обеих сторон., поскольку это только вопрос времени и неудачи, когда вы можете столкнуться с невосприимчивыми сокетами.