Unter Linux (meine Live-Server sind auf RHEL 5.5 - die folgenden LXR-Links verweisen auf die Kernel-Version), man 7 ip
heißt es:
Eine gebundene lokale TCP-Socket-Adresse ist nach dem Schließen einige Zeit lang nicht verfügbar, es sei denn, das Flag SO_REUSEADDR wurde gesetzt.
Ich benutze nicht SO_REUSEADDR
. Wie lang ist "einige Zeit"? Wie kann ich herausfinden, wie lange es dauert und wie kann ich es ändern?
Ich habe darüber gegoogelt und ein paar Informationen gefunden, von denen keine das wirklich aus der Sicht eines Anwendungsprogrammierers erklärt. Nämlich:
- TCP_TIMEWAIT_LEN in
net/tcp.h
gibt an, "wie lange gewartet werden muss, um den Status TIME-WAIT zu zerstören", und ist auf "ungefähr 60 Sekunden" festgelegt. - / proc / sys / net / ipv4 / tcp_fin_timeout ist "Zeit, den Socket im Zustand FIN-WAIT-2 zu halten, falls er von unserer Seite geschlossen wurde" und "Standardwert ist 60sec".
Ich stolpere über die Lücke zwischen dem Kernel-Modell des TCP-Lebenszyklus und dem Modell des Programmierers, dass Ports nicht verfügbar sind.
man 2 bind
wenn du mir nicht glaubst. Zugegeben, es ist wahrscheinlich nicht das erste, woran Unix-Leute denken, wenn jemand "bind" sagt, also fair genug.bind
, aber das Tag hier wird speziell auf den DNS-Server angewendet. Wir haben nicht für jeden möglichen Systemaufruf Tags.Antworten:
Ich glaube, dass die Idee, dass der Socket für ein Programm nicht verfügbar ist, darin besteht, dass alle TCP-Datensegmente, die sich noch auf dem Weg befinden, eintreffen und vom Kernel verworfen werden. Das heißt, es ist möglich, dass eine Anwendung
close(2)
einen Socket aufruft, aber Verzögerungen oder Pannen weiterleitet, um Pakete zu steuern, oder was Sie der anderen Seite einer TCP-Verbindung erlauben können, für eine Weile Daten zu senden. Die Anwendung hat angegeben, dass sie keine TCP-Datensegmente mehr verarbeiten möchte, daher sollte der Kernel sie einfach verwerfen, sobald sie eingehen.Ich habe ein kleines Programm in C gehackt, das Sie kompilieren und verwenden können, um zu sehen, wie lange das Timeout dauert:
Ich habe dieses Programm auf 3 verschiedenen Computern ausprobiert und erhalte eine variable Zeit zwischen 55 und 59 Sekunden, wenn der Kernel einem Benutzer ohne Rootberechtigung das erneute Öffnen eines Sockets verweigert. Ich habe den obigen Code zu einer ausführbaren Datei mit dem Namen "opener" kompiliert und sie folgendermaßen ausgeführt:
Ich öffnete ein anderes Fenster und tat dies:
Das bewirkt, dass die erste Instanz von "opener" eine Verbindung akzeptiert und dann schließt. Die zweite Instanz von "opener" versucht
bind(2)
jede Sekunde , auf den TCP-Port 7896 zuzugreifen. "opener" meldet eine Verzögerung von 55 bis 59 Sekunden.Beim googeln finde ich, dass die Leute dies empfehlen:
um dieses Intervall zu reduzieren. Es hat bei mir nicht funktioniert. Von den 4 Linux-Rechnern, auf die ich Zugriff hatte, hatten zwei 30 und zwei 60. Ich habe diesen Wert auch auf 10 gesetzt. Kein Unterschied zum "opener" -Programm.
Dies tun:
Dinge geändert haben. Der zweite "Öffner" brauchte nur ca. 3 Sekunden, um seinen neuen Sockel zu bekommen.
quelle