Oficjalne powody komunikatu „Oprogramowanie spowodowało przerwanie połączenia: błąd zapisu gniazda”


157

Biorąc pod uwagę ten fragment śledzenia stosu

Przyczyna: java.net.SocketException: oprogramowanie spowodowało przerwanie połączenia: błąd zapisu gniazda
 w java.net.SocketOutputStream.socketWrite0 (metoda macierzysta)

Próbowałem odpowiedzieć na następujące pytania:

  1. Jaki kod zgłasza ten wyjątek? (JVM? / Tomcat? / Mój kod?)
  2. Co powoduje zgłoszenie tego wyjątku?

Odnośnie nr 1:

Źródło JVM firmy Sun nie zawiera dokładnie tego komunikatu, ale myślę, że tekst Oprogramowanie spowodowało przerwanie połączenia: błąd zapisu gniazda pochodzi z natywnej implementacji SocketOutputStream:

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

Odnośnie nr 2

Domyślam się, że jest to spowodowane przerwaniem połączenia przez klienta przed uzyskaniem pełnej odpowiedzi (np. Wysłał żądanie, ale przed otrzymaniem pełnej odpowiedzi został zamknięty / zakończony / offline)

Pytania:

  1. Czy powyższe założenia są prawidłowe (nr 1 i nr 2)?
  2. Czy można to odróżnić od sytuacji: „nie można pisać do klienta z powodu błędu sieciowego po stronie serwera ”? czy też spowoduje to wyświetlenie tego samego komunikatu o błędzie?
  3. I najważniejsze: czy istnieje oficjalny dokument (np. Firmy Sun) stwierdzający powyższe?

Muszę mieć dowód, że ten ślad stosu jest „winą” klienta gniazda i nie ma nic, co serwer mógłby zrobić, aby tego uniknąć. (z wyjątkiem przechwytywania wyjątku lub używania SocketOutputStream innej niż Sun JVM, chociaż oba nie pozwalają uniknąć faktu zakończenia pracy klienta)


Mam ten problem podczas anulowania pobierania za pomocą przeglądarki Firefox
koppor

Hej Eran, otrzymuję również ten wyjątek podczas wysyłania / pisania ( outs.write(audioBytes);) byte[]do OutputStream. Kiedy dźwięk jest odtwarzany i podczas odtwarzania, jeśli użytkownik kliknie jakiekolwiek inne menu (które wysyła żądanie serwera), otrzymałem ten sam błąd na konsoli. więc czy można bezpiecznie zignorować ten wyjątek?
Amogh

1
@Amogh - Na to wygląda, tak. Zasadniczo z tego, co opisują odpowiedzi, jest to błąd specyficzny dla systemu Windows, ale zakładam, że w Linuksie dostaniesz ten sam wyjątek tylko z innym sformułowaniem ... przez gniazdo do jakiejś odległej lokalizacji X i X zostały rozłączone w środku, ale jestem pewien, że nie jest to najdokładniejszy sposób na opisanie tego)
Eran Medan

1
U mnie stało się tak, gdy serwer bazy danych został zrestartowany, a aplikacja nadal próbowała zapytać, używając wcześniej otwartych połączeń. Nie jestem pewien, dlaczego nie zostały one odświeżone, ponieważ używamy puli opartej na DBCP. Jednak ponowne uruchomienie aplikacji rozwiązało problem.
Kshitiz Sharma

Odpowiedzi:


55

Ten błąd może wystąpić, gdy system sieci lokalnej przerywa połączenie, na przykład gdy WinSock zamyka ustanowione połączenie po niepowodzeniu retransmisji danych (odbiorca nigdy nie potwierdza danych przesłanych przez gniazdo strumienia danych).

Zobacz ten artykuł MSDN . Zobacz także Niektóre informacje dotyczące „Przerwania połączenia przez oprogramowanie” .



3
@MatGessel Ten artykuł po prostu powtarza zamieszanie i dodaje kilka własnych. WSAECONNABORTED to kod błędu Winsock, więc prawdopodobnie nie może być dla niego wyjaśnienia Berkeley. Opisana sytuacja dotycząca serwera HTTP spowodowałaby ECONNRESET, a nie WSAECONNABORTED.
Markiz Lorne

@EJP, otrzymuję również ten wyjątek podczas wysyłania / zapisywania (outs.write (audioBytes);) bajtu [] do OutputStream. Kiedy dźwięk jest odtwarzany i podczas odtwarzania, jeśli użytkownik kliknie jakiekolwiek inne menu (które wysyła żądanie serwera), otrzymałem ten sam błąd na konsoli. więc czy można bezpiecznie zignorować ten wyjątek?
Amogh

1
@rustyx Wszystkie trzy cytowane tutaj źródła podają, że jest to spowodowane awariami ACK. Jeśli masz źródło dla własnego roszczenia, zacytuj je.
Markiz Lorne

2
To nie jest prawdziwa odpowiedź, ponieważ nie zawiera informacji potrzebnych do dalszego rozwiązania problemu. Odpowiedź brzmi w zasadzie „coś złego stało się w sieci”. Byłoby naprawdę pomocne, aby zrozumieć, jakie dalsze dzienniki i inne zapisy aktywności pozwolą mi określić podstawowy problem.
Derek Bennett

11

Element java.net.SocketExceptionjest generowany, gdy wystąpi błąd podczas tworzenia lub uzyskiwania dostępu do gniazda (na przykład TCP ). Zwykle może to być spowodowane przerwaniem połączenia przez serwer (bez jego prawidłowego zamknięcia), a więc przed uzyskaniem pełnej odpowiedzi. W większości przypadków może to być spowodowane przekroczeniem limitu czasu (np. Odpowiedź zajmuje zbyt dużo czasu lub serwer jest przeciążony żądaniami) lub klient wysłał SYN, ale nie otrzymał ACK (potwierdzenie zakończenia połączenia) . W przypadku problemów z limitem czasu możesz rozważyć zwiększenie wartości limitu czasu.

Wyjątek gniazda zwykle zawiera określony szczegółowy komunikat dotyczący problemu.

Przykład szczegółowych wiadomości:

  • Oprogramowanie spowodowało przerwanie połączenia: recv failed.

    Błąd wskazuje na próbę wysłania wiadomości, a połączenie zostało przerwane przez serwer. Jeśli zdarzyło się to podczas łączenia się z bazą danych, może to być związane z użyciem niekompatybilnego sterownika Connector / J JDBC .

    Możliwe rozwiązanie: upewnij się, że masz odpowiednie biblioteki / sterowniki w CLASSPATH.

  • Oprogramowanie spowodowało przerwanie połączenia: połącz.

    Może się to zdarzyć, gdy wystąpi problem z połączeniem z pilotem. Na przykład z powodu programu antywirusowego odrzucającego żądania zdalnej poczty .

    Możliwe rozwiązanie: sprawdź usługę skanowania antywirusowego, czy blokuje port dla wychodzących żądań połączeń.

  • Oprogramowanie spowodowało przerwanie połączenia: błąd zapisu gniazda.

    Możliwe rozwiązanie: upewnij się, że piszesz w strumieniu odpowiednią długość bajtów. Więc sprawdź dokładnie, co wysyłasz. Zobacz ten wątek .

  • Reset połączenia przez peera: błąd zapisu gniazda / Połączenie przerwane przez partnera: błąd zapisu gniazda

    Aplikacja nie sprawdziła, czy po stronie serwera upłynął limit czasu utrzymywania połączenia.

    Możliwe rozwiązanie: upewnij się, że HttpClient ma wartość różną od null przed odczytem z połączenia. E13222_01

  • Połączenie zostało zresetowane przez partnera.

    Połączenie zostało zakończone przez peera (serwer).

  • Reset połączenia.

    Połączenie zostało przerwane przez klienta lub zamknięte przez koniec połączenia serwera z powodu żądania przesłanego do żądania.

    Zobacz: Co powoduje mój java.net.SocketException: Resetowanie połączenia?


Tylko jeden z tych 6 punktów faktycznie odpowiada na pytanie nieprawidłowo. Kilka innych również się myli. Aplikacja nie może „sprawdzić, czy po stronie serwera upłynął limit czasu utrzymywania połączenia”. HttpClientIstota nullnie może ewentualnie spowodować SocketException. Niepisanie poprawnej długości do strumienia też nie.
Markiz Lorne,

9

Widziałem to najczęściej, gdy korporacyjna zapora sieciowa na stacji roboczej / laptopie przeszkadza, przerywa połączenie.

na przykład. Mam proces serwera i proces klienta na tym samym komputerze. Serwer nasłuchuje na wszystkich interfejsach (0.0.0.0), a klient próbuje nawiązać połączenie z interfejsem public / home (nie dotyczy interfejsu sprzężenia zwrotnego 127.0.0.1).

Jeśli w urządzeniu jest odłączona sieć (np. Wyłączone Wi-Fi), połączenie jest tworzone. Jeśli urządzenie jest podłączone do sieci firmowej (bezpośrednio lub VPN), połączenie jest tworzone.

Jeśli jednak urządzenie jest podłączone do publicznej sieci Wi-Fi (lub sieci domowej), zapora ogniowa uruchamia i przerywa połączenie. W tej sytuacji podłączenie klienta do interfejsu pętli zwrotnej działa dobrze, ale nie do interfejsu domowego / publicznego.

Mam nadzieję że to pomoże.


3
Zapory sieciowe uniemożliwiają połączenia. Pytanie dotyczy resetowania istniejącego połączenia.
Markiz Lorne

4

Aby udowodnić, który komponent zawodzi, monitorowałbym komunikację TCP / IP za pomocą programu wireshark i sprawdzał, kto aktywnie zamyka port. Istotne mogą być również limity czasu.


Nikt nie zamyka portu. System operacyjny przerywa połączenie.
Markiz Lorne

@EJP Widziałem, jak to się dzieje, gdy jest przeciążony i zabraknie pamięci. Nie jestem pewien, czy to system operacyjny zamyka połączenie, ale JVM szaleje.
Zee

1
@Zee Istnieje różnica między zamknięciem portu, który jest widoczny jako FIN w Wireshark, a przerwaniem połączenia, które tak nie jest.
Markiz Lorne

2

Czy sprawdziłeś kod źródłowy Tomcat i źródło JVM? To może dać ci więcej pomocy.

Myślę, że twoje ogólne myślenie jest dobre. Spodziewałbym się ConnectExceptionw scenariuszu, że nie możesz się połączyć. Powyższe wygląda na bardzo zależne od klienta.


3
Tak, sprawdziłem. Źródła Tomcata nie zawierały żadnej permutacji zdania, dzięki.
Eran Medan

1
Nie, nie sprawdził źródła Tomcat ORAZ JVM.
Stephen C

Lub jeśli sprawdził źródło JVM, to nie sprawdził wszystkich.
Stephen C

1
@Ehrann - ciąg wiadomości jest najprawdopodobniej w źródłach natywnych. Ale powinieneś również sprawdzić dziennik zdarzeń. IMO, ta ostatnia prawdopodobnie będzie zawierała więcej informacji.
Stephen C

6
Ten komunikat pochodzi z systemu operacyjnego.
Markiz Lorne

2

Dla każdego, kto używa prostych programów Client Server i otrzymuje ten błąd, jest to problem niezamkniętych (lub zamkniętych na wczesnym etapie) strumieni wejściowych lub wyjściowych.


2
Nie, nie jest. Oznaczałoby to wyciek z gniazda, który ostatecznie spowodowałby wyczerpanie FD.
Markiz Lorne

0

Miałem ten sam problem.
Często ten rodzaj błędu występuje, ponieważ klient zamknął połączenie, a serwer nadal próbuje pisać na tym kliencie.
Dlatego upewnij się, że połączenie klienta jest otwarte, dopóki serwer nie zakończy przetwarzania strumienia wyjściowego.
I jeszcze jedno, nie zapomnij zamknąć strumienia wejściowego i wyjściowego.

Mam nadzieję że to pomoże.
A jeśli nadal masz problem, opisz go szczegółowo tutaj.


3
@BhavinChhatrola Nie, nieprawidłowa odpowiedź. Opisana sytuacja powoduje „resetowanie połączenia przez peera”, a nie błąd w pytaniu.
Markiz Lorne,

0

Ten błąd przydarzył mi się podczas testowania mojej usługi mydła z klientem SoapUI, w zasadzie próbowałem uzyskać bardzo duży komunikat (> 500kb), a SoapUI zamknęło połączenie przez przekroczenie limitu czasu.

W SoapUI przejdź do:

Plik -> Preferencje - Limit czasu gniazda (ms)

... i wpisz dużą wartość, na przykład 180000 (3 minuty), nie będzie to idealne rozwiązanie problemu, ponieważ plik jest w rzeczywistości zbyt duży, ale przynajmniej otrzymasz odpowiedź.


0

Zamknięte połączenie w innym kliencie

W moim przypadku błąd był następujący:

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

Otrzymano go w eclipse podczas debugowania aplikacji Java korzystającej z bazy danych H2. Źródłem błędu było to, że początkowo otworzyłem bazę danych za pomocą SQuirreL, aby ręcznie sprawdzić integralność. Użyłem flagi, aby umożliwić wiele połączeń z tą samą bazą danych (tjAUTO_SERVER=TRUE ), Więc nie było problemu z połączeniem się z bazą danych z javy.

Błąd pojawił się, gdy po jakimś czasie - jest to długi proces java - postanowiłem zamknąć SQuirreL, aby zwolnić zasoby. Wygląda na to, że SQuirreL był „właścicielem” instancji serwera DB i że został on zamknięty za pomocą połączenia SQuirreL.

Ponowne uruchomienie aplikacji Java nie spowodowało ponownego wystąpienia błędu.

config

  • System Windows 7
  • Eclipse Kepler
  • SQuirreL 3.6
  • org.h2.Driver w wersji 1.4.192

0

W moim przypadku rozwinąłem stronę klienta i serwera i mam wyjątek:

Przyczyna: argumenty krosowania błędów; zagnieżdżony wyjątek: java.net.SocketException: oprogramowanie spowodowało przerwanie połączenia: błąd zapisu do gniazda

gdy klasy w kliencie i serwerze są różne. Nie pobieram klas serwera (interfejsów) na klienta, po prostu dodaję te same pliki w projekcie. Ale ścieżka musi być dokładnie taka sama. Na przykład w projekcie serwera mam pakiety java \ rmi \ services z niektórymi serviceInterface i implementacjami, muszę utworzyć ten sam pakiet w projekcie klienta. Jeśli zmienię to na przykład przez java / rmi / server / services, otrzymam powyższy wyjątek. Ten sam wyjątek, jeśli wersja interfejsu różni się między klientem a serwerem (nawet z nieumyślnym dodaniem pustego wiersza ... Myślę, że rmi robi coś w rodzaju skrótu klas w celu sprawdzenia wersji ... nie wiem ... gdyby tak było Wsparcie ...


-1

Mój serwer rzucał ten wyjątek w ciągu 2 dni i rozwiązałem go, przenosząc funkcję rozłączania za pomocą:

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

Do końca wątku aukcji. czy to komuś pomoże.


-1

W sytuacji opisanej poniżej strona klienta zgłosi taki wyjątek:

Serwer jest proszony o uwierzytelnienie certyfikatu klienta, ale klient dostarcza certyfikat, którego funkcja Rozszerzone użycie klucza nie obsługuje uwierzytelniania klienta, więc serwer nie akceptuje certyfikatu klienta, a następnie zamyka połączenie.


Ta odpowiedź jest nieprawidłowa. W przypadku, gdy opiszesz, zostanie wyrzucony wyjątek SSLException.
Prezydent James K. Polk

faktycznie rzuca SocketException, tak jak obecne pytanie, które testowałem
xiaoming

-1

ssl po stronie klienta wyrzuci taki wyjątek w poniższej sytuacji (testowałem),:

serwer jest proszony o uwierzytelnienie certyfikatu klienta, ale klient dostarcza certyfikat, którego Rozszerzone użycie klucza nie obsługuje uwierzytelniania klienta.


-3

Miałem ten sam problem z wireMock podczas mockowania pozostałych wywołań API. Wcześniej definiowałem serwer w ten sposób:

WireMockServer wireMockServer = null;

Ale należy to zdefiniować jak pokazano poniżej:

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

To spowodowałoby, a NullPointerExceptionnie ten problem.
Markiz Lorne,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.