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_WAITist 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_WAITauf 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_WAITauf die Client-Seite zu verlagern, wo es Probleme geben kann Serverseite, wo es kein Problem ist.
Die Clientseite TIME_WAITist 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_LINGER0 Timeout oder Einmischung in tcp_tw sysctls) bekämpfen Sie die Clientseite, TIME_WAITindem 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_WAIThilfreich die Serverseite überhaupt ist. Der Grund TIME_WAITist sogar da, weil es verhindert, dass abgestandene TCPFragmente in Streams injiziert werden , zu denen sie nicht mehr gehören. Für die Clientseite wird TIME_WAITdies erreicht, indem einfach unmöglich gemacht wird, eine Verbindung mit denselben ip:portPaaren 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_WAITkonnten Verbindungen auf genau demselben Portpaar sofort und erfolgreich wiederhergestellt werden, und auf der Clientseite TIME-WAITschlug die zweite Iteration zu connect()Recht fehl
Zusammenfassend ist die Frage zweifach:
- Tut serverseitig
TIME_WAITwirklich nichts und bleibt es einfach so, weil es dasRFCerfordert? - Ist der Grund der Empfehlung, dass der Client close () initiiert, weil der Server
TIME_WAITunbrauchbar ist?
TIME_WAIT.