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:
- Jaki kod zgłasza ten wyjątek? (JVM? / Tomcat? / Mój kod?)
- 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:
- Czy powyższe założenia są prawidłowe (nr 1 i nr 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?
- 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)
outs.write(audioBytes);
)byte[]
doOutputStream
. 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?Odpowiedzi:
Zobacz ten artykuł MSDN . Zobacz także Niektóre informacje dotyczące „Przerwania połączenia przez oprogramowanie” .
źródło
Element
java.net.SocketException
jest 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:
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.
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ń.
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 .
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 zakończone przez peera (serwer).
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?
źródło
HttpClient
Istotanull
nie może ewentualnie spowodowaćSocketException
. Niepisanie poprawnej długości do strumienia też nie.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.
źródło
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.
źródło
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ę
ConnectException
w scenariuszu, że nie możesz się połączyć. Powyższe wygląda na bardzo zależne od klienta.źródło
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.
źródło
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.
źródło
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.
... 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ź.
źródło
Zamknięte połączenie w innym kliencie
W moim przypadku błąd był następujący:
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 (tj
AUTO_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
źródło
W moim przypadku rozwinąłem stronę klienta i serwera i mam wyjątek:
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 ...
źródło
Mój serwer rzucał ten wyjątek w ciągu 2 dni i rozwiązałem go, przenosząc funkcję rozłączania za pomocą:
Do końca wątku aukcji. czy to komuś pomoże.
źródło
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.
źródło
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.
źródło
Miałem ten sam problem z wireMock podczas mockowania pozostałych wywołań API. Wcześniej definiowałem serwer w ten sposób:
Ale należy to zdefiniować jak pokazano poniżej:
źródło
NullPointerException
nie ten problem.