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

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

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

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

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

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

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

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

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

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

Вопросы:

  • Правильны ли следующие допущения (# 1 и # 2)?
  • Может ли это отличаться от ситуации: "Не удалось написать клиенту из-за сетевой ошибки на стороне сервера"? или будет отображать одно и то же сообщение об ошибке?
  • И самое главное: Есть ли официальный документ (например, от Sun), указав выше?

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

Ответ 1

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

Смотрите эту статью MSDN. См. Также некоторую информацию о "Отключение соединения из-за программного обеспечения"

Ответ 2

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Ответ 3

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

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

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

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

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

Ответ 4

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

Ответ 5

Вы проверили исходный код Tomcat и источник JVM? Это может помочь вам.

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

Ответ 6

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

Ответ 7

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

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

Ответ 8

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

В SoapUI перейдите к:

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

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

Ответ 9

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

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

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

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

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

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

CONFIG

  • Windows 7
  • Eclipse Kepler
  • SQuirreL 3.6
  • org.h2.Driver ver 1.4.192

Ответ 10

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

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

В конец листинга. если это кому-то помогло.

Ответ 11

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

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

Ответ 12

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

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

Ответ 13

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

WireMockServer wireMockServer = null;

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

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