Otrzymuję następujący błąd podczas próby odczytu z gniazda. Robię readInt()
się na to InputStream
, a ja otrzymuję ten błąd. Po przeczytaniu dokumentacji sugeruje to, że część połączenia będąca klientem zamknęła połączenie. W tym scenariuszu jestem serwerem.
Mam dostęp do plików dziennika klienta i to nie zamyka połączenia, aw rzeczywistości jego pliki dziennika sugerują, że zamykam połączenie. Czy ktoś ma pojęcie, dlaczego tak się dzieje? Co jeszcze sprawdzić? Czy dzieje się tak, gdy istnieją lokalne zasoby, które być może osiągają progi?
Zwracam uwagę, że mam następujący wiersz:
socket.setSoTimeout(10000);
tuż przed readInt()
. Jest ku temu powód (długa historia), ale po prostu ciekawy, czy są okoliczności, w których może to doprowadzić do wskazanego błędu? Mam serwer działający w moim IDE i zdarzyło mi się zostawić moje IDE w punkcie przerwania, a następnie zauważyłem, że dokładnie te same błędy zaczęły pojawiać się w moich własnych dziennikach w moim IDE.
W każdym razie, tylko o tym wspominając, mam nadzieję, że nie jest to czerwony śledź. :-(
źródło
Odpowiedzi:
Istnieje kilka możliwych przyczyn.
Drugi koniec celowo zresetował połączenie, w sposób, którego nie będę tutaj dokumentować. Jest to rzadkie i generalnie niepoprawne, gdy oprogramowanie to robi, ale nie jest to nieznane w przypadku oprogramowania komercyjnego.
Częściej jest to spowodowane zapisem do połączenia, którego drugi koniec został już normalnie zamknięty. Innymi słowy, błąd protokołu aplikacji.
Może to być również spowodowane zamknięciem gniazda, gdy w buforze odbiorczym gniazda znajdują się nieprzeczytane dane.
W systemie Windows „przerwanie połączenia przez oprogramowanie”, co nie jest tym samym, co „resetowanie połączenia”, jest spowodowane problemami z przesyłaniem danych z sieci. Jest na ten temat artykuł w bazie wiedzy Microsoft.
źródło
Reset połączenia oznacza po prostu, że odebrano TCP RST. Dzieje się tak, gdy Twój partner otrzymuje dane, których nie może przetworzyć, a może to mieć różne przyczyny.
Najprościej jest zamknąć gniazdo, a następnie zapisać więcej danych w strumieniu wyjściowym. Zamykając gniazdo, powiedziałeś swojemu rówieśnikowi, że skończyłeś mówić i może zapomnieć o Twoim połączeniu. Kiedy i tak wysyłasz więcej danych w tym strumieniu, peer odrzuca je z RST, aby poinformować Cię, że nie nasłuchuje.
W innych przypadkach interweniująca zapora ogniowa lub nawet sam zdalny host mogą „zapomnieć” o połączeniu TCP. Może się tak zdarzyć, jeśli nie wysyłasz żadnych danych przez długi czas (2 godziny to typowy limit czasu) lub ponieważ peer został ponownie uruchomiony i utracił informacje o aktywnych połączeniach. Wysłanie danych na jednym z tych niedziałających połączeń spowoduje również RST.
Aktualizacja w odpowiedzi na dodatkowe informacje:
Przyjrzyj się uważnie, jak obchodzisz się z
SocketTimeoutException
. Ten wyjątek jest zgłaszany, jeśli skonfigurowany limit czasu zostanie przekroczony podczas blokowania operacji gniazda. Stan samego gniazda nie jest zmieniany po zgłoszeniu tego wyjątku, ale jeśli program obsługi wyjątków zamknie gniazdo, a następnie spróbuje do niego zapisać, nastąpi zresetowanie połączenia.setSoTimeout()
ma na celu zapewnienie prostego sposobu na wyrwanie się zread()
operacji, która w innym przypadku mogłaby zostać zablokowana na zawsze, bez robienia brudnych rzeczy, takich jak zamykanie gniazda z innego wątku.źródło
Ilekroć mam takie dziwne problemy, zwykle siadam z narzędziem takim jak WireShark i patrzę na surowe dane przesyłane tam iz powrotem. Możesz być zaskoczony, gdy coś jest rozłączane, a powiadomienie jest wyświetlane tylko wtedy, gdy próbujesz czytać.
źródło
Żenująco to powiedzieć, ale kiedy miałem ten problem, po prostu błędem było to, że zamykałem połączenie, zanim przeczytałem wszystkie dane. W przypadkach, gdy zwracano małe ciągi, działało, ale było to prawdopodobnie spowodowane tym, że cała odpowiedź była buforowana, zanim ją zamknąłem.
W przypadku zwracania większej ilości tekstu zgłaszany był wyjątek, ponieważ więcej niż wracał bufor.
Możesz sprawdzić, czy nie ma tego przeoczenia. Pamiętaj, że otwieranie adresu URL jest jak plik, pamiętaj, aby go zamknąć (zwolnić połączenie) po całkowitym przeczytaniu.
źródło
Powinieneś bardzo dokładnie sprawdzić pełny ślad,
Mam aplikację używającą gniazda serwera i naprawiłem
java.net.SocketException: Connection reset
przypadek.W moim przypadku dzieje się tak podczas odczytu z
Socket
obiektu clientSocket, który z jakiegoś powodu zamyka swoje połączenie. (Utrata sieci, awaria zapory lub aplikacji albo zamierzone zamknięcie)Właściwie to przywracałem połączenie, gdy wystąpił błąd podczas odczytu z tego obiektu Socket.
Ciekawostką jest to,
for my JAVA Socket
że jeśli klient łączy się z myServerSocket
i zamyka swoje połączenie bez wysyłania jakichkolwiekis.read()
wywołań rekurencyjnych, wydaje się, że będąc w nieskończonej pętli while do odczytu z tego gniazda, próbujesz odczytać z zamkniętego połączenia. Jeśli używasz czegoś takiego jak poniżej do operacji odczytu;Następnie dostajesz stos i śledzenie czegoś takiego jak poniżej
Po prostu zamknąłem ServerSocket i odnowiłem połączenie i czekałem na dalsze przychodzące połączenia klientów
Spowoduje to ponowne nawiązanie połączenia w przypadku utraty nieznanego gniazda klienta
Nie mogłem znaleźć innego sposobu, ponieważ jak widać na poniższym obrazku, nie możesz zrozumieć, czy połączenie jest utracone, czy nie bez a
try and catch
, ponieważ wszystko wydaje się w porządku. Otrzymałem tę migawkę podczasConnection reset
ciągłego otrzymywania .źródło
Miałem ten sam błąd. Znalazłem teraz rozwiązanie problemu. Problem polegał na tym, że program klienta kończył pracę, zanim serwer odczytał strumienie.
źródło
Miałem ten problem z systemem SOA napisanym w Javie. Uruchomiłem zarówno klienta, jak i serwer na różnych komputerach fizycznych i działały dobrze przez długi czas, a potem te paskudne resetowania połączenia pojawiły się w dzienniku klienta i nie było nic dziwnego w dzienniku serwera. Ponowne uruchomienie klienta i serwera nie rozwiązało problemu. W końcu odkryliśmy, że sterta po stronie serwera była raczej pełna, więc zwiększyliśmy pamięć dostępną dla maszyny JVM: problem rozwiązany! Zauważ, że w logu nie było OutOfMemoryError: pamięć była po prostu ograniczona, a nie wyczerpana.
źródło
Sprawdź wersję Java swojego serwera. Zdarzyło mi się to, ponieważ mój Weblogic 10.3.6 był na JDK 1.7.0_75, który był na TLSv1. Pozostały punkt końcowy, który próbowałem wykorzystać, wyłączał wszystko poniżej TLSv1.2.
Domyślnie Weblogic próbował wynegocjować najsilniejszy wspólny protokół. Zobacz szczegóły tutaj: Problemy z ustawieniem właściwości systemu https.protocols dla połączeń HTTPS .
Dodałem szczegółowe rejestrowanie SSL, aby zidentyfikować obsługiwane TLS. Oznacza to, że do uzgadniania używany był protokół TLSv1.
-Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack
Rozwiązałem to, wypychając tę funkcję do naszego produktu zgodnego z JDK8, JDK8 domyślnie ustawia TLSv1.2. W przypadku osób ograniczonych do JDK7 z powodzeniem przetestowałem również obejście dla Java 7, aktualizując do TLSv1.2. Użyłem tej odpowiedzi: Jak włączyć TLS 1.2 w Javie 7
źródło
Miałem również ten problem z programem Java, który próbował wysłać polecenie na serwer przez SSH. Problem dotyczył maszyny wykonującej kod Java. Nie miał uprawnień do łączenia się ze zdalnym serwerem. Metoda write () działała prawidłowo, ale metoda read () generowała java.net.SocketException: Connection reset. Rozwiązałem ten problem, dodając klucz SSH klienta do znanych kluczy zdalnego serwera.
źródło
Z mojego doświadczenia wynika, że często napotykam następujące sytuacje;
Jeśli pracujesz w firmie korporacyjnej, skontaktuj się z zespołem ds. Sieci i bezpieczeństwa. Ponieważ w żądaniach skierowanych do usług zewnętrznych może być konieczne udzielenie pozwolenia dla odpowiedniego punktu końcowego.
Innym problemem jest to, że certyfikat SSL mógł wygasnąć na serwerze, na którym działa aplikacja.
źródło