Come funziona davvero il server TIME_WAIT sul lato server?


11

So che ci sono alcune domande SE su questo, e credo di averne letto quante ne siano importanti prima di arrivare a questo punto.

Per "lato server TIME_WAIT" intendo lo stato di una coppia di socket lato server che aveva il suo close () avviato sul lato server.

Vedo spesso queste affermazioni che mi sembrano contraddittorie:

  1. Il lato server TIME_WAITè innocuo
  2. È necessario progettare le app di rete in modo che i client inizino close (), quindi il client deve essere supportato da TIME_WAIT

Il motivo per cui trovo questo contraddittorio è perché TIME_WAITsul client può esserci un problema: il client può esaurire le porte disponibili, quindi in sostanza si consiglia di spostare l'onere TIME_WAITsul lato client dove può essere un problema, dal lato server dove non è un problema.

Il lato client TIME_WAITè ovviamente solo un problema per un numero limitato di casi d'uso. La maggior parte delle soluzioni client-server coinvolgerebbe un server e molti client, i client di solito non gestiscono un volume di connessioni sufficientemente elevato da costituire un problema e, anche se lo fanno, ci sono una serie di raccomandazioni per "sanely" ( al contrario di SO_LINGER0 timeout, o intromettersi con tcp_tw sysctls) combattere il lato client TIME_WAITevitando di creare troppe connessioni troppo rapidamente. Ma ciò non è sempre possibile, ad esempio per la classe di applicazioni come:

  • sistemi di monitoraggio
  • generatori di carico
  • proxy

D'altra parte, non capisco nemmeno come il lato server TIME_WAITsia utile. Il motivo TIME_WAITè anche lì, perché impedisce l'iniezione di TCPframmenti stantii in flussi a cui non appartengono più. Per il lato client TIME_WAITsi ottiene semplicemente rendendo impossibile creare una connessione con le stesse ip:portcoppie che questa connessione non valida avrebbe potuto avere (le coppie utilizzate sono bloccate da TIME_WAIT). Ma per il lato server, questo non può essere impedito poiché l'indirizzo locale avrà la porta accettante e sarà sempre lo stesso, e il server non può (AFAIK, ho solo la prova empirica) negare la connessione semplicemente perché un peer in entrata creerebbe la stessa coppia di indirizzi già esistente nella tabella dei socket.

Ho scritto un programma che mostra che TIME-WAIT sul lato server viene ignorato. Inoltre, poiché il test è stato eseguito su 127.0.0.1, il kernel deve avere un bit speciale che gli dica persino se si tratta di un lato server o lato client (poiché altrimenti la tupla sarebbe la stessa).

Fonte: http://pastebin.com/5PWjkjEf , testato su Fedora 22, configurazione di rete predefinita.

$ gcc -o rtest rtest.c -lpthread
$ ./rtest 44400 s # will do server-side close
Will initiate server close
... iterates ~20 times successfully
^C
$ ss -a|grep 44400
tcp    TIME-WAIT  0      0            127.0.0.1:44400         127.0.0.1:44401   
$ ./rtest 44500 c # will do client-side close
Will initiate client close
... runs once and then
connecting...
connect: Cannot assign requested address

Quindi, per il lato server TIME_WAIT, le connessioni sulla stessa identica coppia di porte potrebbero essere ristabilite immediatamente e con successo, e per il lato client TIME-WAIT, sulla seconda iterazione connect()non è riuscita correttamente

Per riassumere, la domanda è duplice:

  • Il lato server TIME_WAITnon fa davvero nulla e viene lasciato in quel modo perché lo RFCrichiede?
  • È la ragione per cui la raccomandazione è per il client di avviare close () perché il server TIME_WAITè inutile?

Non rimarrai senza porte a meno che tu non abbia un solo client. Hai 65535 porte per ogni combinazione di IP client / server. La connessione da 1.2.3.4:1111 è diversa da 4.3.2.1:1111. Ci vogliono solo pochi byte di memoria per ogni connessione TIME_WAIT.
Marki555,

Risposte:


1

In termini TCP lato server qui significa l'host che ha il socket nello stato LISTEN.

RFC1122 consente al socket nello stato TIME-WAIT di accettare una nuova connessione con alcune condizioni

        When a connection is closed actively, it MUST linger in
        TIME-WAIT state for a time 2xMSL (Maximum Segment Lifetime).
        However, it MAY accept a new SYN from the remote TCP to
        reopen the connection directly from TIME-WAIT state, if it:

Per dettagli esatti sulle condizioni, consultare RFC1122 . Mi aspetto che ci sia anche un OPEN passivo corrispondente sul socket (socket in stato LISTEN).

OPEN attivo (chiamata di connessione lato client) non ha tale eccezione e deve dare errore quando il socket è in TIME-WAIT, come da RFC793 .

La mia ipotesi per la raccomandazione sul client (in termini TCP l'host che esegue OPEN attivo cioè connettersi) avviata vicino è più o meno la tua, che nel caso comune diffonde i socket TIME-WAIT su più host dove ci sono molte risorse per le prese. Nel caso comune i client non inviano SYN che riutilizzerebbe i socket TIME-WAIT sul server. Sono d'accordo che applicare tale raccomandazione dipende ancora dal caso d'uso.


0

Questo è probabilmente l'esempio più chiaro di ciò che fa TIME-WAIT e soprattutto perché è importante. Spiega anche perché evitare alcuni dei suggerimenti "esperti" su macchine Linux per "ridurre" i TEMPI DI ATTESA.


Non spiega ancora cosa succede quando viene avviata una connessione client-> server e un server ha quella coppia bloccata in un TIME_WAIT
Pawel Veselov

Consulta stackoverflow.com/questions/1490196/… : la risposta è ciò che stai cercando.
Khushil,

0

Una sessione tcp è identificata dal tupple (sourceIP, sourcePort, destIP, destPort). Quindi TIME_WAIT funziona su ogni connessione tcp.

Per quanto riguarda il lato di chiusura, in alcuni scenari, la chiusura dal lato client può ridurre i socket TIME_WAIT sul server, riducendo così leggermente la memoria. Nei casi in cui lo spazio socket può essere esaurito (a causa dell'esaurimento delle porte effimero) (ad esempio client avidi con molte connessioni allo stesso server), questo problema dovrebbe essere risolto da qualsiasi parte.


Spiega per favore; quando chiedi se il TW sul lato server fa qualcosa, ti chiedi se la stessa connessione può essere riutilizzata durante il periodo TW. La risposta è no perché la connessione, come definita da tupple, ha un posto nella tabella tcp del server. Se il client tenta di aprire presto la stessa connessione, riceverà un RST, negando efficacemente la connessione tcp. A proposito, l'articolo di Khushil è molto descrittivo.
basos

Mi dispiace molto, la tua risposta in realtà risponde alla domanda, l'ho letto male e ho ritirato il mio commento. Tuttavia, sembra anche essere errato, poiché ho un codice che sembra dimostrare che non esiste protezione dal lato server TIME_WAIT(ho aggiornato la domanda con tali informazioni). Il riferimento di @ Khushil non copre i TIME_WAITcasi sul lato server in modo sufficientemente dettagliato.
Pawel Veselov,

-2

Con un protocollo inaffidabile non puoi mai essere sicuro di aver ricevuto l'ultimo messaggio dal tuo dispositivo peer, quindi è pericoloso presumere che il tuo peer abbia riattaccato il telefono piuttosto improvvisamente. È un grosso svantaggio del protocollo TCP che solo 65000 porte possono essere aperte contemporaneamente. Ma il modo per ovviare a questo sarebbe quello di passare a una server farm, che si ridimensiona meglio con il carico, che riciclando rapidamente i numeri di porta. Alla fine del client è altamente improbabile che si esauriscano le porte se si tratta di una workstation di base.


Mi dispiace molto, ma questo non risponde alla mia domanda.
Pawel Veselov,
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.