Je sais qu'il y a pas mal de questions SE à ce sujet, et je crois que j'en ai lu autant qu'il le faut avant d'en arriver là.
Par "côté serveur TIME_WAIT
", j'entends l'état d'une paire de sockets côté serveur dont la fermeture () a été déclenchée côté serveur.
Je vois souvent ces déclarations qui me semblent contradictoires:
- Côté serveur
TIME_WAIT
est inoffensif - Vous devez concevoir vos applications réseau pour que les clients lancent close (), donc le client doit
TIME_WAIT
La raison pour laquelle je trouve cela contradictoire est que TIME_WAIT
le client peut être un problème - le client peut manquer de ports disponibles, donc essentiellement ce qui précède recommande de déplacer la charge du TIME_WAIT
côté client où il peut être problématique, du côté serveur où ce n'est pas un problème.
Le côté client TIME_WAIT
n'est bien sûr qu'un problème pour un nombre limité de cas d'utilisation. La plupart des solutions client-serveur impliqueraient un serveur et de nombreux clients, les clients ne traitent généralement pas avec un volume de connexions suffisamment élevé pour que ce soit un problème, et même s'ils le font, il existe un certain nombre de recommandations à "sainement" ( par opposition à SO_LINGER
0 timeout, ou se mêler de tcp_tw sysctls) combattre côté client TIME_WAIT
en évitant de créer trop de connexions trop rapidement. Mais ce n'est pas toujours possible, par exemple pour une classe d'applications comme:
- systèmes de surveillance
- générateurs de charge
- procurations
D'un autre côté, je ne comprends même pas du tout comment le côté serveur TIME_WAIT
est utile. La raison TIME_WAIT
est même là, car elle empêche d'injecter des TCP
fragments périmés dans des flux auxquels ils n'appartiennent plus. Pour le côté client, TIME_WAIT
cela est accompli en rendant simplement impossible la création d'une connexion avec les mêmes ip:port
paires que cette connexion périmée aurait pu avoir (les paires utilisées sont verrouillées par TIME_WAIT
). Mais pour le côté serveur, cela ne peut pas être évité car l'adresse locale aura le port d'acceptation, et sera toujours la même, et le serveur ne peut pas (AFAIK, je n'ai que la preuve empirique) refuser la connexion simplement parce que un homologue entrant créerait la même paire d'adresses qui existe déjà dans la table des sockets.
J'ai écrit un programme qui montre que TIME-WAIT côté serveur est ignoré. De plus, comme le test a été fait sur 127.0.0.1, le noyau doit avoir un bit spécial qui lui indique même si c'est du côté serveur ou côté client (car sinon le tuple serait le même).
Source: http://pastebin.com/5PWjkjEf , testé sur Fedora 22, configuration réseau par défaut.
$ 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
Ainsi, pour le côté serveur TIME_WAIT
, les connexions sur la même paire de ports peuvent être rétablies immédiatement et avec succès, et pour le côté client TIME-WAIT
, la deuxième itération a connect()
échoué correctement.
Pour résumer, la question est double:
- Le côté serveur ne fait-il
TIME_WAIT
vraiment rien et est-il laissé de cette façon parce que leRFC
requiert? - Est-ce la raison pour laquelle le client recommande d'initialiser close () parce que le serveur
TIME_WAIT
est inutile?
TIME_WAIT
.