Qual è la differenza tra connessione e timeout di lettura per i socket?


180

3 domande:

  1. Qual è la differenza tra connessione e timeout di lettura per i socket?

  2. Che cosa significa timeout della connessione impostato su "infinito"? In quale situazione può rimanere in un ciclo infinito? e cosa può innescare che il ciclo infinito muore?

  3. Che cosa significa timeout di lettura impostato su "infinito"? In quale situazione può rimanere in un ciclo infinito? e cosa può innescare che il ciclo infinito muore?

Risposte:


227

1) Qual è la differenza tra connessione e timeout di lettura per le prese?

Il timeout della connessione è il timeout per stabilire la connessione iniziale; vale a dire il completamento dell'handshake della connessione TCP. Il timeout di lettura è il timeout in attesa di leggere i dati 1 . In particolare, se il server non riesce a inviare un byte <timeout> secondi dopo l'ultimo byte, verrà generato un errore di timeout di lettura.

2) Cosa significa "timeout connessione" impostato su "infinito"? In quale situazione può rimanere in un ciclo infinito? e cosa può innescare che il ciclo infinito muore?

Significa che il tentativo di connessione può potenzialmente bloccarsi per sempre. Non esiste un loop infinito, ma il tentativo di connessione può essere sbloccato da un altro thread che chiude il socket. (Una Thread.interrupt()chiamata può anche fare il trucco ... non sono sicuro.)

3) Cosa significa "timeout di lettura" impostato su "infinito"? In quale situazione può rimanere in un ciclo infinito? Cosa può innescare la fine del ciclo infinito?

Significa che una chiamata a readsul flusso di socket potrebbe bloccarsi per sempre. Ancora una volta non esiste un loop infinito, ma readpuò essere sbloccato da una Thread.interrupt()chiamata, chiudendo il socket e (ovviamente) l'altra estremità inviando dati o chiudendo la connessione.


1 - Non è ... come pensava un commentatore ... il timeout su quanto tempo un socket può essere aperto o inattivo.


8

Questi sono i valori di timeout applicati da JVM per stabilire la connessione TCP e attendere la lettura dei dati dal socket.

Se il valore è impostato su infinito, non aspetterai per sempre. Significa semplicemente che JVM non ha timeout e il sistema operativo sarà responsabile di tutti i timeout. Tuttavia, i timeout sul sistema operativo potrebbero essere molto lunghi. Su una rete lenta, ho visto timeout fino a 6 minuti.

Anche se si imposta il valore di timeout per socket, potrebbe non funzionare se il timeout si verifica nel codice nativo. Possiamo riprodurre il problema su Linux collegandoci a un host bloccato dal firewall o scollegando il cavo sullo switch.

L'unico approccio sicuro per gestire il timeout TCP è eseguire il codice di connessione in un thread diverso e interrompere il thread quando impiega troppo tempo.


"Se il valore è impostato su infinito, non aspetterai per sempre." Finché non si tratta di discutere sul significato di "infinito", può sicuramente succedere che tu aspetti molto a lungo. Abbiamo avuto un caso qui, dove HttpURLConnection.getResponseCode()era appeso per apprx. una settimana fino a quando non abbiamo riavviato il processo. Ovviamente non è stato impostato alcun timeout sul lato JVM e nemmeno un timeout sul lato del sistema operativo Linux.
Tom Fink,

Il paragrafo finale non è corretto. Una connessione scadrà al massimo dopo circa un minuto. Un thread separato è completamente inutile. Puoi sicuramente avere letture che durano per sempre se non ci sono dati. Tuttavia Javadoc ha torto sul fatto che il timeout di connessione predefinito sia infinito. Non lo è.
Marchese di Lorne,

1
@comeGetSome Non è corretto. È possibile chiudere il socket per l'input. Ciò farà sì che la lettura bloccata raggiunga la fine del flusso.
Marchese di Lorne,

@comeGetSome: ho dovuto implementarlo usando un thread che contiene un riferimento a una connessione URL HTTP aperta. Quando detto thread chiude la connessione, l'altro thread genera "java.net.SocketException: Socket chiuso". Grazie a bug JDK-8075484 per avermelo fatto fare!
fmcato,

@comeGetSome Sicuramente puoi chiamare Socket.shutdownInput()senza tenere la mano? NB Questi timeout sono applicati da TCP, non da JVM.
Marchese di Lorne,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.