java.net.SocketException: сброс подключения
Я получаю следующую ошибку при попытке чтения из сокета. Я делаю readInt()
над этим InputStream
, и я получаю эту ошибку. При просмотре документации можно предположить, что клиентская часть соединения закрыла соединение. В этом сценарии я являюсь сервером.
У меня есть доступ к файлам журнала клиента, и он не закрывает соединение, а его файлы журнала предполагают, что я закрываю соединение. Итак, у кого-нибудь есть идея, почему это происходит? Что еще нужно проверить? Возникает ли это, когда есть локальные ресурсы, которые, возможно, достигают пороговых значений?
Я отмечаю, что у меня есть следующая строка:
socket.setSoTimeout(10000);
непосредственно перед readInt()
. Для этого есть причина (долгая история), но просто любопытно, существуют ли обстоятельства, при которых это может привести к указанной ошибке? У меня запущен сервер в моей IDE, и так получилось, что моя IDE застряла на точке останова, а затем я заметил, что точно такие же ошибки начали появляться в моих собственных журналах в моей IDE.
В любом случае, просто упоминаю об этом, надеюсь, не отвлекающий маневр.
Переведено автоматически
Ответ 1
Существует несколько возможных причин.
Другой конец намеренно сбросил соединение способом, который я не буду здесь документировать. Прикладное программное обеспечение делает это редко и, как правило, некорректно, но это не является чем-то необычным для коммерческого программного обеспечения.
Чаще всего это вызвано записью в соединение, которое на другом конце уже закрыто в обычном режиме. Другими словами, ошибка протокола приложения.
Это также может быть вызвано закрытием сокета, когда в буфере приема сокета остаются непрочитанные данные.
В Windows "прерывание соединения по программному обеспечению", что не то же самое, что "сброс подключения", вызвано сетевыми проблемами при отправке с вашей стороны. Об этом есть статья в базе знаний Microsoft.
Ответ 2
Сброс подключения просто означает, что был получен TCP RST. Это происходит, когда ваш одноранговый узел получает данные, которые он не может обработать, и на это могут быть различные причины.
Самый простой - это когда вы закрываете сокет, а затем записываете дополнительные данные в выходной поток. Закрывая сокет, вы сообщаете своему партнеру, что закончили общение, и он может забыть о вашем подключении. Когда вы все равно отправляете больше данных по этому потоку, одноранговый узел отклоняет их с помощью RST, чтобы сообщить вам, что он не прослушивает.
В других случаях подключенный брандмауэр или даже сам удаленный хост могут "забыть" о вашем TCP-соединении. Это может произойти, если вы долгое время не отправляете никаких данных (2 часа - обычный тайм-аут) или потому, что одноранговый узел был перезагружен и потерял информацию об активных соединениях. Отправка данных по одному из этих несуществующих подключений также вызовет RST.
Обновление в ответ на дополнительную информацию:
Внимательно посмотрите на вашу обработку SocketTimeoutException
. Это исключение возникает, если превышен настроенный тайм-аут при блокировке операции с сокетами. Состояние самого сокета не изменяется при возникновении этого исключения, но если ваш обработчик исключений закроет сокет, а затем попытается выполнить запись в него, вы окажетесь в состоянии сброса соединения. setSoTimeout()
предназначен для предоставления вам чистого способа прервать read()
операцию, которая в противном случае могла бы быть заблокирована навсегда, без выполнения грязных действий, таких как закрытие сокета из другого потока.
Ответ 3
Всякий раз, когда у меня возникают подобные странные проблемы, я обычно сажусь с помощью такого инструмента, как WireShark, и смотрю на необработанные данные, передаваемые взад и вперед. Вы можете быть удивлены, когда что-то отключается, и вы получаете уведомление только при попытке чтения.
Ответ 4
Вам следует очень тщательно проверить полную трассировку,
У меня есть серверное приложение для сокетов, и я исправил java.net.SocketException: Connection reset
случай.
В моем случае это происходит при чтении из clientSocket Socket
объекта, соединение с которым по какой-либо причине закрыто. (Потеря сети, сбой брандмауэра или приложения или предполагаемое закрытие)
На самом деле я восстанавливал соединение, когда получил сообщение об ошибке при чтении из этого объекта сокета.
Socket clientSocket = ServerSocket.accept();
is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
int readed = is.read(); // WHERE ERROR STARTS !!!
Интересно то, что for my JAVA Socket
если клиент подключается к моему ServerSocket
и закрывает свое соединение, ничего не отправляя, is.read()
вызывается повторно.Кажется, что из-за бесконечного цикла while для чтения из этого сокета вы пытаетесь читать из закрытого соединения.
Если вы используете что-то вроде приведенного ниже для операции чтения;
while(true)
{
Receive();
}
Затем вы получаете stackTrace примерно так, как показано ниже, снова и снова
java.net.SocketException: Socket is closed
at java.net.ServerSocket.accept(ServerSocket.java:494)
Что я сделал, так это просто закрыл ServerSocket, обновил свое соединение и стал ждать дальнейших входящих клиентских подключений
String Receive() throws Exception
{
try {
int readed = is.read();
....
}catch(Exception e)
{
tryReConnect();
logit(); //etc
}
//...
}
Это восстанавливает мое соединение при потерях неизвестного клиентского сокета
private void tryReConnect()
{
try
{
ServerSocket.close();
//empty my old lost connection and let it get by garbage col. immediately
clientSocket=null;
System.gc();
//Wait a new client Socket connection and address this to my local variable
clientSocket= ServerSocket.accept(); // Waiting for another Connection
System.out.println("Connection established...");
}catch (Exception e) {
String message="ReConnect not successful "+e.getMessage();
logit();//etc...
}
}
Я не смог найти другого способа, потому что, как вы видите на изображении ниже, вы не можете понять, потеряно соединение или нет без try and catch
, потому что все кажется правильным. Я получил этот снимок, пока получал Connection reset
непрерывно.