Kürzlich habe ich ein bisschen Code gesehen, der so aussah (wobei sock natürlich ein Socket-Objekt ist):
sock.shutdown(socket.SHUT_RDWR)
sock.close()
Was genau ist der Grund, um das Herunterfahren des Sockets und das Schließen des Sockets aufzurufen? Wenn es einen Unterschied macht, wird dieser Socket für nicht blockierende E/A verwendet.
Hier ist eine Erklärung :
Sobald ein Socket nicht mehr benötigt wird, kann das aufrufende Programm den Socket verwerfen, indem eine Close-Subroutine auf den Socket-Deskriptor angewendet wird. Wenn einem zuverlässigen Übermittlungssocket bei einem Abschluss Daten zugeordnet sind, versucht das System weiterhin, Daten zu übertragen. Wenn die Daten jedoch noch nicht zugestellt wurden, werden sie vom System verworfen. Wenn das Anwendungsprogramm keine ausstehenden Daten verwendet, kann es die Shutdown-Subroutine auf dem Socket verwenden, bevor es geschlossen wird.
Das Aufrufen von close
und shutdown
hat zwei unterschiedliche Auswirkungen auf den zugrunde liegenden Socket.
Als Erstes muss darauf hingewiesen werden, dass der Socket eine Ressource im zugrunde liegenden Betriebssystem ist und dass mehrere Prozesse ein Handle für denselben zugrunde liegenden Socket haben können.
Wenn Sie close
aufrufen, wird die Anzahl der Handles um eins verringert, und wenn die Anzahl der Handles Null erreicht hat, werden der Socket und die zugehörige Verbindung normal geschlossen (wobei effektiv ein FIN/EOF an gesendet wird) der Peer) und der Socket wird freigegeben.
Hier ist zu beachten, dass die Verbindung nicht geschlossen wird und die Zuordnung des Sockets nicht aufgehoben wird, wenn die Anzahl der Handles nicht Null erreicht, da ein anderer Prozess noch ein Handle zum Socket hat.
Wenn Sie dagegen shutdown
zum Lesen und Schreiben aufrufen, wird die zugrunde liegende Verbindung geschlossen und ein FIN/EOF an den Peer gesendet, unabhängig davon, wie viele Prozesse über Handles für den Socket verfügen. Allerdings geht nicht hebt die Zuordnung des Sockets auf und Sie müssen danach noch close anrufen.
Erklärung zum Herunterfahren und Schließen: Graceful shutdown (msdn)
Das Herunterfahren (in Ihrem Fall) zeigt an, dass am anderen Ende der Verbindung keine weitere Absicht besteht, aus dem Socket zu lesen oder in diesen zu schreiben. Anschließend wird durch Schließen der dem Socket zugeordnete Speicher freigegeben.
Das Weglassen des Herunterfahrens kann dazu führen, dass der Socket im Stapel der Betriebssysteme verweilt, bis die Verbindung ordnungsgemäß geschlossen wurde.
IMO sind die Namen 'shutdown' und 'close' irreführend, 'close' und 'destroy' würden ihre Unterschiede betonen.
es wird direkt in der Socket-Programmieranleitung erwähnt ( py2 / py )
Verbindung trennen
Genau genommen sollten Sie
shutdown
für einen Socket verwenden, bevor Sieclose
damit beginnen. Dasshutdown
ist eine Empfehlung für den Socket am anderen Ende. Abhängig von dem Argument, das Sie übergeben, kann dies bedeuten: " Ich werde nicht mehr senden, aber ich werde trotzdem zuhören", oder " Ich höre nicht zu, Gute Befreiung ! ”. Die meisten Socket-Bibliotheken werden jedoch von Programmierern verwendet, die diese Etikette vernachlässigen, sodass einclose
normalerweise dasselbe wieshutdown(); close()
ist. In den meisten Situationen ist ein explizites Herunterfahren nicht erforderlich....
Ist dieser Code oben nicht falsch?
Der Close-Aufruf direkt nach dem Shutdown-Aufruf kann dazu führen, dass der Kernel ohnehin alle ausgehenden Puffer löscht.
Laut http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable braucht man zwischen dem Herunterfahren und dem Schließen warten, bis das Lesen 0 zurückgibt.
es gibt einige Arten des Herunterfahrens: http://msdn.Microsoft.com/en-us/library/system.net.sockets.socket.shutdown.aspx . * nix ist ähnlich.
Beim Herunterfahren (1) wird der Socket no gezwungen, weitere Daten zu senden
Dies ist nützlich in
1- Pufferspülung
2- Seltsame Fehlererkennung
3- Sichere Bewachung
Lassen Sie mich näher erläutern, dass beim Senden von Daten von A nach B nicht garantiert wird, dass sie an B gesendet werden. Es wird nur garantiert, dass sie an den A os-Puffer gesendet werden, der sie wiederum an den B os-Puffer sendet
Wenn Sie also shutdown (1) für A aufrufen, leeren Sie den Puffer von A und es wird ein Fehler ausgelöst, wenn der Puffer nicht leer ist, dh: Es wurden noch keine Daten an den Peer gesendet
Dies ist jedoch irreversibel. Sie können dies also tun, nachdem Sie alle Ihre Daten vollständig gesendet haben und sicherstellen möchten, dass sie mindestens im Peer-OS-Puffer gespeichert sind