Używam klienta http apache commons do wywołania adresu URL za pomocą metody post, aby opublikować parametry i rzadko rzuca poniższy błąd.
java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:105)
at java.io.FilterOutputStream.write(FilterOutputStream.java:80)
at org.apache.commons.httpclient.methods.ByteArrayRequestEntity.writeRequest(ByteArrayRequestEntity.java:90)
at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:499)
at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2114)
at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
Czy ktoś może zasugerować, co powoduje ten wyjątek i jak go debugować?
Odpowiedzi:
Jest to spowodowane:
W obu przypadkach masz źle zdefiniowany lub zaimplementowany protokół aplikacji.
Jest trzeci powód, którego tutaj nie będę dokumentował, ale który polega na tym, że peer podejmuje celowe działanie, aby zresetować, a nie prawidłowo zamknąć połączenie.
źródło
XMLHttpRequest.abort()
).W naszym przypadku doświadczyliśmy tego podczas wykonywania testu obciążenia na naszym serwerze aplikacji. Okazało się, że musimy dodać dodatkową pamięć do naszej maszyny JVM, ponieważ kończyła się. To rozwiązało problem.
Spróbuj zwiększyć ilość pamięci dostępnej dla maszyny JVM i / lub monitoruj użycie pamięci w przypadku wystąpienia tych błędów.
źródło
SocketException: Przerwany potok jest spowodowany przez „drugi koniec” (klient lub serwer) zamykający połączenie, podczas gdy kod odczytuje z połączenia lub zapisuje do niego.
Jest to bardzo częsty wyjątek w aplikacjach typu klient / serwer, które odbierają ruch od klientów lub serwerów poza kontrolą aplikacji. Na przykład klient jest przeglądarką. Jeśli przeglądarka wykonuje wywołanie Ajax i / lub użytkownik po prostu zamyka stronę lub przeglądarkę, może to skutecznie nieoczekiwanie przerwać całą komunikację. Zasadniczo zobaczysz ten błąd za każdym razem, gdy drugi koniec zakończy swoją aplikację, a ty tego nie przewidziałeś.
Jeśli wystąpi ten wyjątek w aplikacji, oznacza to, że należy sprawdzić kod, w którym występuje IO (wejście / wyjście) i zawinąć go blokiem try / catch, aby przechwycić ten wyjątek IOException. To do Ciebie należy decyzja, jak postąpić w tej pół-prawidłowej sytuacji.
W twoim przypadku najwcześniejszym miejscem, w którym nadal masz kontrolę, jest wywołanie
HttpMethodDirector.executeWithRetry
- więc upewnij się, że połączenie jest opakowane blokiem try / catch i postępuj z nim tak, jak uważasz za stosowne.Zdecydowanie odradzam rejestrowanie błędów specyficznych dla SocketException-Broken Pipe na jakichkolwiek innych poziomach niż debug / trace. W przeciwnym razie można to wykorzystać jako formę ataku DOS (Denial Of Service) poprzez wypełnienie dzienników. Spróbuj wzmocnić i przetestować aplikację pod kątem tego typowego scenariusza.
źródło
Wszystkie otwarte strumienie i połączenia muszą być prawidłowo zamknięte, więc przy następnej próbie użycia obiektu urlConnection nie generuje on błędu. Na przykład następująca zmiana kodu naprawiła błąd.
Przed:
Po:
źródło
BufferedOutputStream
zawsze wywołujeclose()
swój podstawowy strumień wyjściowy (a więc strumień wyjściowyurlConnection
). Zobacz docs.oracle.com/javase/6/docs/api/java/io/… i docs.oracle.com/javase/6/docs/api/java/io/... Więc kiedy dzwoniszos.close()
, powinno być już zamknięte . Nie?Zaimplementowałem funkcję pobierania danych przez serwer FTP i znalazłem tam ten sam wyjątek podczas wznawiania tego pobierania. Aby rozwiązać ten wyjątek, zawsze będziesz musiał rozłączyć się z poprzednią sesją i utworzyć nową instancję klienta oraz nowe połączenie z serwerem. To samo podejście może być pomocne również w przypadku HTTPClient.
źródło
Miałem ten sam problem, kiedy tworzyłem prostą aplikację Java, która nasłuchuje na określonym TCP. Zwykle nie miałem problemu, ale po uruchomieniu testu warunków skrajnych zauważyłem, że niektóre połączenie zrywało się z błędem
socket write exception
.Po dochodzeniu znalazłem rozwiązanie, które rozwiązuje mój problem. Wiem, że to pytanie jest dość stare, ale wolę podzielić się moim rozwiązaniem, ktoś może uznać je za przydatne.
Problem dotyczył tworzenia ServerSocket. Czytałem z Javadoc, że jest domyślny limit 50 oczekujących gniazd. Jeśli spróbujesz otworzyć inne połączenie, zostaną one odrzucone. Rozwiązanie polega po prostu na zmianie tej domyślnej konfiguracji po stronie serwera. W poniższym przypadku tworzę serwer Socket, który nasłuchuje na porcie TCP
10_000
i akceptuje maksymalną200
liczbę oczekujących gniazd.Z Javadoc ServerSocket :
źródło
Problem może polegać na tym, że wdrożone pliki nie są aktualizowane przy użyciu poprawnych metod RMI. Sprawdź, czy interfejs RMI ma zaktualizowane parametry lub zaktualizowane struktury danych, których nie ma Twój klient. Lub że twój klient RMI nie ma parametrów różniących się od tych, które ma twoja wersja serwera.
To tylko zgadywanie. Po ponownym wdrożeniu plików klas mojej aplikacji serwerowej i ponownym przetestowaniu problem „zepsutej rury” zniknął.
źródło
Powyższe odpowiedzi ilustrują przyczynę tego
java.net.SocketException: Broken pipe
: drugi koniec zamknął połączenie. Chciałbym podzielić się doświadczeniem, co się stało, gdy go spotkałem:Content-Type
nagłówek jest omyłkowo ustawiony jako większy niż w rzeczywistości jest treść żądania (w rzeczywistości nie było jej wcale)Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception java.net.SocketTimeoutException: null
java.net.SocketException: Broken pipe
ponieważ klient go zamknął.Czasami tomcat nie zgłasza zepsutego wyjątku pip, ponieważ wyjątek timeout zamyka połączenie, dlaczego taka różnica też mnie dezorientuje.
źródło
Content-Type
Nagłówka nie podaje numeru, więc to nie może być „większy” niż cokolwiek innego. Wyjątki przekroczenia limitu czasu nie zamykają gniazda. Odpowiedź nie ma żadnego sensu.Na przykład należy zwiększyć parametr „backlog” swojego serwera ServerSocket
źródło
Przyczyną jest to, że zdalny peer zamyka swoje gniazdo (na przykład awaria), więc jeśli spróbujesz na przykład zapisać do niego dane, otrzymasz to. aby rozwiązać ten problem, zabezpiecz operacje odczytu / zapisu do gniazda między (try catch), a następnie zarządzaj przypadkiem utraty połączenia w catch (odnów połączenie, zatrzymaj program itp.):
źródło