Ich weiß, dass es dazu einige SE-Fragen gibt, und ich glaube, ich habe so viele davon gelesen, wie es wichtig ist, bevor ich zu diesem Punkt komme.
Mit "serverseitig TIME_WAIT
" meine ich den Status eines serverseitigen Socket-Paares, dessen close () auf der Serverseite initiiert wurde.
Ich sehe oft diese Aussagen, die mir widersprechen:
- Serverseitig
TIME_WAIT
ist harmlos - Sie sollten Ihre Netzwerk-Apps so gestalten, dass Clients close () initiieren, damit der Client das trägt
TIME_WAIT
Der Grund, warum ich diesen Widerspruch finde, ist, dass TIME_WAIT
auf dem Client ein Problem auftreten kann - dem Client können die verfügbaren Ports ausgehen. Daher empfiehlt das oben Gesagte im Wesentlichen, die Last TIME_WAIT
auf die Client-Seite zu verlagern, wo es Probleme geben kann Serverseite, wo es kein Problem ist.
Die Clientseite TIME_WAIT
ist natürlich nur für eine begrenzte Anzahl von Anwendungsfällen ein Problem. Die meisten Client-Server-Lösungen umfassen einen Server und viele Clients. Clients haben normalerweise nicht genügend Verbindungsvolumen, um ein Problem zu verursachen, und selbst wenn dies der Fall ist, gibt es eine Reihe von Empfehlungen, die "vernünftig" sind ( Im Gegensatz zu SO_LINGER
0 Timeout oder Einmischung in tcp_tw sysctls) bekämpfen Sie die Clientseite, TIME_WAIT
indem Sie vermeiden, zu schnell zu viele Verbindungen herzustellen. Dies ist jedoch nicht immer möglich, beispielsweise für Anwendungsklassen wie:
- Überwachungssysteme
- Lastgeneratoren
- Proxies
Auf der anderen Seite verstehe ich nicht einmal, wie TIME_WAIT
hilfreich die Serverseite überhaupt ist. Der Grund TIME_WAIT
ist sogar da, weil es verhindert, dass abgestandene TCP
Fragmente in Streams injiziert werden , zu denen sie nicht mehr gehören. Für die Clientseite wird TIME_WAIT
dies erreicht, indem einfach unmöglich gemacht wird, eine Verbindung mit denselben ip:port
Paaren herzustellen, die diese veraltete Verbindung hätte haben können (die verwendeten Paare werden von gesperrt TIME_WAIT
). Auf der Serverseite kann dies jedoch nicht verhindert werden, da die lokale Adresse den akzeptierenden Port hat und immer gleich ist und der Server die Verbindung nicht einfach deshalb verweigern kann (AFAIK, ich habe nur den empirischen Beweis) Ein eingehender Peer würde dasselbe Adresspaar erstellen, das bereits in der Socket-Tabelle vorhanden ist.
Ich habe ein Programm geschrieben, das zeigt, dass serverseitiges TIME-WAIT ignoriert wird. Da der Test auf 127.0.0.1 durchgeführt wurde, muss der Kernel außerdem ein spezielles Bit haben, das sogar angibt, ob es sich um eine Server- oder eine Clientseite handelt (da sonst das Tupel dasselbe wäre).
Quelle: http://pastebin.com/5PWjkjEf , getestet auf Fedora 22, Standardnetzkonfiguration.
$ 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
Auf der Serverseite TIME_WAIT
konnten Verbindungen auf genau demselben Portpaar sofort und erfolgreich wiederhergestellt werden, und auf der Clientseite TIME-WAIT
schlug die zweite Iteration zu connect()
Recht fehl
Zusammenfassend ist die Frage zweifach:
- Tut serverseitig
TIME_WAIT
wirklich nichts und bleibt es einfach so, weil es dasRFC
erfordert? - Ist der Grund der Empfehlung, dass der Client close () initiiert, weil der Server
TIME_WAIT
unbrauchbar ist?
TIME_WAIT
.