Официальные причины для «программного обеспечения вызвало прерывание соединения: ошибка записи в сокет»


157

Учитывая этот фрагмент трассировки стека

Причина: java.net.SocketException: программное обеспечение вызвало прерывание соединения: ошибка записи сокета
 в java.net.SocketOutputStream.socketWrite0 (собственный метод)

Я пытался ответить на следующие вопросы:

  1. Какой код выдает это исключение? (JVM? / Tomcat? / Мой код?)
  2. Что вызывает это исключение?

Относительно № 1:

Источник JVM от Sun не содержит этого точного сообщения, но я думаю, что текст Software вызвал прерывание соединения: ошибка записи в сокет произошла из собственной реализации SocketOutputStream:

private native void socketWrite0(FileDescriptor fd, byte[] b, int off,
                 int len) throws IOException;

Относительно № 2

Я предполагаю, что это вызвано тем, что клиент разорвал соединение до получения полного ответа (например, отправил запрос, но до получения полного ответа он был закрыт / прекращен / отключен)

Вопросы:

  1. Верны ли вышеизложенные предположения (№ 1 и № 2)?
  2. Можно ли это дифференцировать от ситуации: «не удалось написать клиенту из-за сетевой ошибки на стороне сервера »? или это выдает то же сообщение об ошибке?
  3. И самое главное: есть ли официальный документ (например, от Sun), в котором говорится выше?

Мне нужно иметь доказательство того, что эта трассировка стека является «ошибкой» клиента сокета, и сервер ничего не мог бы сделать, чтобы избежать этого. (кроме перехвата исключения или использования не Sun JVM SocketOutputStream, хотя оба не избегают того факта, что клиент завершил работу)


У меня есть эта проблема при отмене загрузки с Firefox
koppor

Эй, Эран, я также получаю это исключение при отправке / записи ( outs.write(audioBytes);) byte[]в OutputStream. Когда звук воспроизводится и во время воспроизведения, если пользователь нажимает на любое другое меню (которое отправляет запрос на сервер), я получаю ту же ошибку на консоли. так безопасно ли игнорировать это исключение?
Amogh

1
@ Amogh - Кажется, да. Исходя из того, что описывают ответы, это ошибка, специфичная для Windows, но я предполагаю, что в Linux вы получите то же исключение только с другой формулировкой ... (Мои непрофессионалы понимают, что в основном это происходит, когда вы отправляете через розетку в какое-то удаленное место X и X были отключены в середине, но я уверен, что это не самый точный способ описать это)
Эран Медан

1
Для меня это произошло, когда сервер баз данных был перезапущен, и приложение все еще пыталось сделать запрос, используя ранее открытые соединения. Не уверен, почему они не были обновлены, так как мы используем пул на основе DBCP. Но перезапуск приложения устранил проблему.
Кшитиз Шарма

Ответы:


55

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

Смотрите эту статью MSDN . См. Также Некоторая информация о «Прерывание соединения из-за программного обеспечения» .



3
@MatGessel Эта статья просто повторяет путаницу и добавляет некоторые свои. WSAECONNABORTED - это код ошибки Winsock, поэтому объяснение Беркли не может быть. Описанная ситуация с HTTP-сервером приведет к ECONNRESET, а не WSAECONNABORTED.
Маркиз Лорн

@EJP, я также получаю это исключение при отправке / записи (outs.write (audioBytes);) byte [] в OutputStream. Когда звук воспроизводится и во время воспроизведения, если пользователь нажимает на любое другое меню (которое отправляет запрос на сервер), я получаю ту же ошибку на консоли. так безопасно ли игнорировать это исключение?
Amogh

1
@rustyx Все три источника, цитируемые здесь, утверждают, что он вызван ошибками ACK. Если у вас есть источник для вашей заявки, пожалуйста, укажите его.
Маркиз Лорн

2
Это не реальный ответ, поскольку он не дает вам информации для дальнейшего решения проблемы. Ответ здесь в основном «что-то плохое произошло в сети». Было бы очень полезно понять, какие дополнительные журналы и другие записи активности могут позволить мне точно определить основную проблему.
Дерек Беннетт

11

java.net.SocketExceptionВыбрасывается при возникновении ошибки создания или доступа сокет (например, TCP ). Обычно это может быть вызвано тем, что сервер разорвал соединение (без надлежащего закрытия), поэтому перед получением полного ответа. В большинстве случаев это может быть вызвано либо проблемой тайм-аута (например, ответ занимает слишком много времени, либо сервер перегружен запросами), либо клиент отправил SYN, но не получил ACK (подтверждение завершения соединения) , Для проблем тайм-аута, вы можете рассмотреть возможность увеличения значения тайм-аута.

Исключение Socket обычно поставляется с указанным сообщением о проблеме.

Пример подробных сообщений:

  • Программное обеспечение вызвало прерывание соединения: сбой recv.

    Ошибка указывает на попытку отправить сообщение, и соединение было прервано вашим сервером. Если это произошло при подключении к базе данных, это может быть связано с использованием несовместимого драйвера JDBC Connector / J .

    Возможное решение: убедитесь, что в вашей CLASSPATH есть нужные библиотеки / драйверы.

  • Программное обеспечение вызвало прерывание соединения: соединение.

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

    Возможное решение: Проверьте службу проверки на вирусы, не блокирует ли порт исходящие запросы на подключение.

  • Программное обеспечение вызвало разрыв соединения: ошибка записи в сокет.

    Возможное решение: убедитесь, что вы записываете правильную длину байтов в поток. Поэтому дважды проверьте, что вы отправляете. Смотрите эту тему .

  • Сброс соединения по пиру: ошибка записи сокета / Соединение прервано по адресу: ошибка записи сокета

    Приложение не проверяет, истекло ли время ожидания активности на стороне сервера.

    Возможное решение: убедитесь, что HttpClient не нулевой, прежде чем читать из соединения. E13222_01

  • Сброс соединения по пиру.

    Соединение было прервано узлом (сервером).

  • Сброс соединения.

    Соединение было прервано клиентом или закрыто серверным концом соединения из-за запроса с запросом.

    Смотрите: Что вызывает мой java.net.SocketException: сброс соединения?


Только один из этих 6 пунктов фактически отвечает на вопрос, неправильно. Некоторые другие тоже неверны. Приложение не может «проверить, истекло ли время ожидания активности на стороне сервера». Существо HttpClientне nullможет быть причиной SocketException. Не запись правильной длины в поток также не делает.
маркиз Лорн

9

Я видел это чаще всего, когда корпоративный брандмауэр на рабочей станции / ноутбуке мешает, он разрывает соединение.

например. У меня есть процесс сервера и процесс клиента на одной машине. Сервер прослушивает все интерфейсы (0.0.0.0), а клиент пытается подключиться к общедоступному / домашнему интерфейсу (обратите внимание, что интерфейс обратной связи 127.0.0.1).

Если у машины отключена сеть (например, отключен Wi-Fi), то соединение установлено. Если машина подключена к корпоративной сети (напрямую или vpn), то соединение формируется.

Однако, если устройство подключено к общедоступной сети Wi-Fi (или домашней сети), брандмауэр отключает соединение. В этой ситуации подключение клиента к интерфейсу обратной связи работает нормально, только не к интерфейсу home / public.

Надеюсь это поможет.


3
Брандмауэры предотвращают соединения. Вопрос в том, чтобы сбросить существующее соединение.
маркиз Лорн

4

Чтобы доказать, какой компонент выходит из строя, я бы отслеживал связь TCP / IP с помощью wireshark и смотрел, кто на самом деле закрывает порт, также могут быть актуальны таймауты.


Никто не закрывает порт. Операционная система прерывает соединение.
маркиз Лорн

@EJP Я видел, как это происходит, когда перегружается и не хватает памяти. Я не уверен, что это ОС, которая закрывает соединение, но JVM сходит с ума.
Зи

1
@Zee Существует разница между закрытием порта, который виден как FIN в Wireshark, и прерыванием соединения, а это не так.
Маркиз Лорн

2

Проверяли ли вы исходный код Tomcat и источник виртуальной машины Java? Это может дать вам больше помощи.

Я думаю, что ваше общее мышление хорошо. Я ожидаю, что ConnectExceptionв сценарии вы не можете подключиться. Вышеприведенное выглядит очень похоже на то, что оно управляется клиентом.


3
Да, я проверил. Источники Tomcat не содержат никакой перестановки предложения, спасибо.
Эран Медан

1
Нет, он не проверял источник Tomcat И источник JVM.
Стивен С.

Или, если он проверил источник JVM, он не проверил все это.
Стивен С.

1
@Ehrann - строка сообщения наиболее вероятна в родных источниках. Но вы также должны проверить журнал событий. ИМО, последний, скорее всего, будет более информативным.
Стивен С.

6
Эта строка сообщения на самом деле приходит из операционной системы.
маркиз Лорн

2

Для тех, кто использует простые программы Client Server и получает эту ошибку, это проблема закрытых (или закрытых до раннего) потоков ввода или вывода.


2
Нет, это не так. Это приведет к утечке из сокета, что в конечном итоге приведет к истощению FD.
Маркиз Лорн

0

Я столкнулся с той же проблемой.
Обычно ошибка такого рода возникает из-за того, что клиент закрыл соединение и сервер все еще пытается выполнить запись на этом клиенте.
Поэтому убедитесь, что у вашего клиента открыто соединение, пока сервер не завершит свой выходной поток.
И еще одна вещь, не забудьте закрыть входной и выходной поток.

Надеюсь это поможет.
И если проблема еще не решена, кратко опишите вашу проблему здесь.


3
@BhavinChhatrola Нет, неправильный ответ. Описанная ситуация вызывает «сброс соединения по пиру», а не ошибку в вопросе.
Маркиз Лорн

0

Эта ошибка произошла со мной во время тестирования моей службы мыла с клиентом SoapUI, в основном я пытался получить очень большое сообщение (> 500 КБ), и SoapUI закрыл соединение по таймауту.

На SoapUI захожу по адресу:

Файл -> Настройки - Тайм-аут сокета (мс)

... и укажите большое значение, например 180000 (3 минуты), это не будет идеальным решением для вашей проблемы, потому что файл на самом деле слишком большой, но по крайней мере у вас будет ответ.


0

Закрытое соединение в другом клиенте

В моем случае ошибка была:

java.net.SocketException: Software caused connection abort: recv failed

Он был получен в Eclipse при отладке Java-приложения, обращающегося к базе данных H2. Источником ошибки было то, что я первоначально открыл базу данных с помощью SQuirreL, чтобы вручную проверить целостность. Я использовал этот флаг для включения нескольких подключений к одной и той же БД (т.е. AUTO_SERVER=TRUE), поэтому не было проблем с подключением к БД из Java.

Ошибка появилась, когда через некоторое время - это долгий процесс Java - я решил закрыть SQuirreL для освобождения ресурсов. Похоже, что SQuirreL был «владельцем» экземпляра сервера БД и что он был закрыт с помощью соединения SQuirreL.

Перезапуск приложения Java снова не выдает ошибку.

конфиг

  • Windows 7
  • Затмение Кеплер
  • SQuirreL 3.6
  • org.h2.Driver ver 1.4.192

0

В моем случае я разработал клиент и сервер, и у меня есть исключение:

Причина: ошибка сортировки аргументов; Вложенное исключение: java.net.SocketException: программное обеспечение вызвало прерывание соединения: ошибка записи в сокет

когда классы в клиенте и на сервере разные. Я не загружаю серверные классы (интерфейсы) на клиенте, я просто добавляю те же файлы в проект. Но путь должен быть точно таким же. Например, в проекте сервера у меня есть пакеты java \ rmi \ services с некоторыми serviceInterface и реализациями, я должен создать такой же пакет в проекте клиента. Если я изменю его, например, на java / rmi / server / services, я получу указанное выше исключение. То же исключение, если версия интерфейса отличается между клиентом и сервером (даже если случайно добавлена ​​пустая строка ... Я думаю, что rmi создает своего рода хэш классов для проверки версии ... Я не знаю ... Если бы это могло Помогите ...


-1

Мой сервер генерировал это исключение в течение 2 дней, и я решил его, переместив функцию отключения с помощью:

outputStream.close();
inputStream.close();
Client.close();

В конец ветки листинга. если это кому-нибудь поможет.


-1

В ситуации, описанной ниже, клиентская сторона выдаст такое исключение:

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


Этот ответ неверен. В случае, если вы опишите SSLException, будет выброшено.
Президент Джеймс К. Полк

на самом деле он выбрасывает SocketException так же, как текущий вопрос, который я тестировал
xiaoming

-1

Клиентская сторона ssl сгенерирует такое исключение в следующей ситуации (я проверял):

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


-3

Я столкнулся с той же проблемой с WireMock, когда высмеивал остальные вызовы API. Ранее я определял сервер следующим образом:

WireMockServer wireMockServer = null;

Но это должно быть определено как показано ниже:

@Rule 
public WireMockRule wireMockRule = new WireMockRule(8089);

Это вызвало бы NullPointerException, а не эту проблему.
Маркиз Лорн
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.