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:
- Il lato server
TIME_WAIT
è innocuo - È 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_WAIT
sul client può esserci un problema: il client può esaurire le porte disponibili, quindi in sostanza si consiglia di spostare l'onere TIME_WAIT
sul 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_LINGER
0 timeout, o intromettersi con tcp_tw sysctls) combattere il lato client TIME_WAIT
evitando 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_WAIT
sia utile. Il motivo TIME_WAIT
è anche lì, perché impedisce l'iniezione di TCP
frammenti stantii in flussi a cui non appartengono più. Per il lato client TIME_WAIT
si ottiene semplicemente rendendo impossibile creare una connessione con le stesse ip:port
coppie 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_WAIT
non fa davvero nulla e viene lasciato in quel modo perché loRFC
richiede? - È la ragione per cui la raccomandazione è per il client di avviare close () perché il server
TIME_WAIT
è inutile?
TIME_WAIT
.