Jaka jest różnica między czasem połączenia a czasem oczekiwania dla gniazd?

180

3 pytania:

  1. Jaka jest różnica między czasem połączenia a czasem oczekiwania dla gniazd?

  2. Co oznacza limit czasu połączenia ustawiony na „nieskończoność”? W jakiej sytuacji może pozostać w bezokoliczniku? i co może spowodować śmierć pętli nieskończoności?

  3. Co oznacza limit czasu odczytu ustawiony na „nieskończoność”? W jakiej sytuacji może pozostać w bezokoliczniku? i co może spowodować śmierć pętli nieskończoności?

Corgrath
źródło

Odpowiedzi:

227

1) Jaka jest różnica między czasem połączenia a czasem oczekiwania dla gniazd?

Limit czasu połączenia jest limitem czasu na nawiązanie pierwszego połączenia; tzn. zakończenie uzgadniania połączenia TCP. Limit czasu odczytu to limit czasu oczekiwania na odczyt danych 1 . W szczególności, jeśli serwer nie wyśle ​​bajtu <limit czasu> sekund po ostatnim bajcie, pojawi się błąd przekroczenia limitu odczytu.

2) Co oznacza limit czasu połączenia ustawiony na „nieskończoność”? W jakiej sytuacji może pozostać w bezokoliczniku? i co może spowodować śmierć pętli nieskończoności?

Oznacza to, że próba połączenia może potencjalnie zablokować na zawsze. Nie ma nieskończonej pętli, ale próbę połączenia można odblokować przez inny wątek zamykający gniazdo. ( Thread.interrupt()Połączenie może również załatwić sprawę ... nie jestem pewien.)

3) Co oznacza limit czasu odczytu ustawiony na „nieskończoność”? W jakiej sytuacji może pozostać w nieskończonej pętli? Co może spowodować zakończenie nieskończonej pętli?

Oznacza to, że wywołanie readw strumieniu gniazda może zostać zablokowane na zawsze. Ponownie nie ma nieskończonej pętli, ale readmożna ją odblokować przez Thread.interrupt()połączenie, zamknięcie gniazda i (oczywiście) drugi koniec wysyłania danych lub zamykania połączenia.


1 - To nie jest ... jak pomyślał jeden z komentatorów ... limit czasu, przez jaki gniazdo może być otwarte lub bezczynne.

Stephen C.
źródło
8

Są to wartości limitu czasu wymuszane przez JVM dla nawiązywania połączenia TCP i oczekiwania na odczyt danych z gniazda.

Jeśli wartość zostanie ustawiona na nieskończoność, nie będziesz czekać wiecznie. Oznacza to po prostu, że JVM nie ma limitu czasu, a system operacyjny będzie odpowiedzialny za wszystkie limity czasu. Jednak limity czasu w systemie operacyjnym mogą być naprawdę długie. W niektórych wolnych sieciach widziałem limity czasu trwające nawet 6 minut.

Nawet jeśli ustawisz wartość limitu czasu dla gniazda, może nie działać, jeśli limit czasu zdarzy się w kodzie natywnym. Możemy odtworzyć problem w systemie Linux, łącząc się z hostem zablokowanym przez zaporę ogniową lub odłączając kabel na przełączniku.

Jedynym bezpiecznym podejściem do obsługi limitu czasu TCP jest uruchomienie kodu połączenia w innym wątku i przerwanie wątku, gdy trwa to zbyt długo.

ZZ Coder
źródło
„Jeśli wartość zostanie ustawiona na nieskończoność, nie będziesz czekać wiecznie”. Dopóki nie chodzi o dyskusję na temat znaczenia „nieskończoności”, może się zdarzyć, że czekasz bardzo długo. Mieliśmy tu przypadek, w którym HttpURLConnection.getResponseCode()wisiał na apprx. tydzień, dopóki nie uruchomimy ponownie procesu. Po stronie JVM najwyraźniej nie ustawiono limitu czasu, a po stronie systemu operacyjnego Linux - limit czasu.
Tom Fink
Ostatni akapit jest nieprawidłowy. Upłynie limit czasu połączenia po około minucie. Oddzielny wątek jest całkowicie niepotrzebny. Na pewno możesz mieć odczyty, które działają wiecznie, jeśli nie ma danych. Jednak Javadoc nie ma racji, że domyślny limit czasu połączenia jest nieskończony. To nie jest
Markiz Lorne
1
@comeGetSome To nie jest poprawne. Możesz zamknąć gniazdo wejściowe. To spowoduje, że zablokowany odczyt napotka koniec strumienia.
Markiz Lorne
@comeGetSome: Musiałem zaimplementować to za pomocą wątku zawierającego odwołanie do otwartego połączenia URL HTTP. Gdy wspomniany wątek zamyka połączenie, drugi wątek generuje „java.net.SocketException: Socket closed”. Dziękuję błędowi JDK-8075484 za zmuszenie mnie do zrobienia tego!
fmcato,
@comeGetSome Na pewno możesz dzwonić Socket.shutdownInput()bez trzymania ręki? Uwaga: Te limity czasu są wymuszane przez TCP, a nie JVM.
Markiz Lorne