2016-08-25 6 views
5

In TCP sagen wir, dass eine Seite der Verbindung ein "aktives Schließen" und die andere Seite ein "passives Schließen" ausführt.Aktiv schließen vs passiv schließen in Bezug auf Socket-API?

In Bezug auf die Linux-Sockets-API, wie unterscheiden Sie die aktive schließen und die passive schließen? Angenommen, wir haben zwei verbundene Linux-TCP-Sockets, A und P, die Informationen über das Protokoll auf Anwendungsebene ausgetauscht haben und beide wissen, dass es Zeit ist, ihre Sockets zu schließen (weder zu senden noch zu empfangen) mehr Daten zu oder von einander).

Wir wollen, dass Sockel A den aktiven Abschluss und P den passiven Abschluss durchführt.

Es gibt ein paar Dinge, die A und P tun könnten. Zum Beispiel:

  • Aufruf shutdown (SHUT_WR)
  • Aufruf recv und erwarten 0 close
  • Anruf zu bekommen.
  • etwas anderes

Welche Kombination dieser Dinge und in welcher Reihenfolge sollte A tun? ... und welche Kombination dieser Dinge und in welcher Reihenfolge sollte P tun?

+1

* BOTH * A und P sollten * ALL * der von Ihnen erwähnten Schritte ausführen: 'shutdown (SHUT_WR)', dann loop 'recv()', bis <<0, dann 'close()' zurückgegeben wird. Die erste Partei, die diese Schritte ausführt, beginnt mit der Schließung, und dann muss die andere Partei die gleichen Schritte ausführen, sobald sie die Schließung feststellt, sodass beide Parteien wissen, dass beide Enden der Verbindung ordnungsgemäß geschlossen wurden. –

+0

@RemyLebeau: Es gibt also keine Möglichkeit zu kontrollieren, welche Seite aktiv ist und welche die passive? –

+1

Es gibt keine reale Sache als "aktiv" vs "passiv" schließen. Eine Partei kann passiv eine Schließung von der anderen Partei feststellen, aber beide Parteien müssen noch ihr Ende der Verbindung schließen. Es gibt jedoch so etwas wie "graceful" vs. "abortive" close, je nachdem, ob "shutdown()" aufgerufen wird und ob linger am Socket aktiviert ist. Sie sollten immer nach eleganten Schlüssen streben, wann immer es möglich ist. –

Antwort

1

In Bezug auf die Linux-Sockets-API, wie unterscheiden Sie die aktive schließen und die passive schließen?

Die ‚aktive‘ close ist einfach Unabhängig davon, welche Seite des Sockels einen ersten FIN oder RST Paket sendet, typischerweise durch close() aufruft.

Welche Kombination dieser Dinge und in welcher Reihenfolge A tun sollte? ... und welche Kombination dieser Dinge und in welcher Reihenfolge sollte P tun?

In der Praxis ist das meiste davon applikations- und anwendungs- protokollspezifisch. Ich werde die minimale/typische Anforderung beschreiben, um Ihre Frage zu beantworten, aber Ihre Laufleistung kann variieren, je nachdem, was Sie gerade erreichen möchten.

Sie kann ersten Anruf shutdown() auf Sockel A, wenn Sie die Kommunikation in eine Richtung oder die andere (oder beide) auf Sockel A. Aus Ihrer Beschreibung beenden wollen, beide Programme bereits wissen, dass sie fertig sind, vielleicht wegen Anwendungsprotokollnachrichten, so dass dies möglicherweise nicht erforderlich ist.

Sie Muss Anruf close() auf Sockel A, um den Sockel und lassen Sie den Dateideskriptor zu schließen.

Auf Sockel-P, halten Sie einfach bis recv()0 zurückkehrt, Lesen und Sie dann muss Anruf close() die Steckdose und lassen Sie den Dateideskriptor zu schließen.

Für weitere Lektüre gibt es eine Reihe von guten Tutorials, und Beej's Guide to Network Programming ist sehr beliebt.

0

Aktiv öffnen ist, wenn Sie explizit connect(2) ausstellen, um eine Verbindung zu einer Remote-Site herzustellen. Die Call-Blöcke, bis Sie die Buchse auf der anderen Seite geöffnet (außer wenn Sie ausgestellt O_NONBLOCKfcntl(2) Anruf vor connect(2) Aufruf.

Passive offen ist, wenn Sie eine Steckdose haben listen(2) ing auf eine Verbindung, und Sie haben noch nicht erteilt Ein accept(2)-Anruf, der normalerweise blockiert, bis Sie eine vollständig geöffnete Verbindung haben und Ihnen einen Socket-Deskriptor für die Kommunikation geben, oder gibt Ihnen sofort einen Socket-Deskriptor, wenn der Verbindungs-Handshake bereits beendet ist, wenn Sie den accept(2) syscall ausgeben (Dies ist ein passives Öffnen.) Die Grenze in der Anzahl der passiv offenen Verbindungen des Kernels kann in Ihrem Namen annehmen, während Sie sich darauf vorbereiten, den accept(2) Systemaufruf zu machen, was der listen(2) Wert genannt wird.

Active schließen ist, was passiert, wenn Sie explizit shutdown(2) oder close(2) Systemaufrufe aufrufen. Wie beim passiven Öffnen gibt es nichts, was Sie tun können, um eine passiv schließen (es ist etwas, was hinter den Kulissen geschieht, Produkt der Aktionen anderer Seite). Sie erkennen ein passive schließen wenn der Sockel eine Ende der Datei Zustand erzeugt (dies ist, read(2)0 Bytes beim Lesen immer wieder), was bedeutet das andere Ende hat ein getan shutdown(2) (oder close(2)) und die Verbindung ist Hälfte (oder voll) geschlossen. Wenn Sie explizit shutdown(2) oder close(2) Ihrer Seite sind, ist es ein aktiver Abschluss.

HINWEIS

wenn das andere Ende hat eine explizite close(2) und weiter Sie auf dem Sockel zu schreiben, wird ein Fehler wegen der Unmöglichkeit des Sendens erhalten, dass die Daten (in diesem Fall können wir über ein sprechen passive close(2) --- eine, die ohne irgendeine explizite Aktion von unserer Seite aufgetreten ist), aber das andere Ende kann eine halb schließen aufrufen shutdown(2). Dadurch sendet der TCP nur ein FIN-Segment und behält den Socket-Deskriptor bei, damit der Thread alle ausstehenden Daten empfangen kann, die gerade übertragen oder noch nicht gesendet wurden. Nur wenn es das FIN Segment des anderen Endes empfängt und bestätigt, wird es Ihnen signalisieren, dass keine Daten mehr übertragen werden.

+0

"Passive Öffnung ist, wenn du eine Steckdose hast, hör zu (2) Verbindung "ist korrekt. Der Rest des Absatzes ist nicht. "Passiv offen" bezieht sich auf den hörenden Sockel selbst. Der Rest des ersten Absatzes handelt von dem 'accept()' -Prozess, und ob es schon eine Verbindung in der Backlog-Queue gab, wenn Sie 'accept()' aufrufen, ist im Grunde irrelevant für alles außer 'accept()' . – EJP

+0

@EJP, Ja, es ist irrelevant, aber * um zu wissen, ob eine passive Verbindung stattgefunden hat, musst du 'accept (2)' syscall * machen und/oder zumindest überprüfen, ob es blockieren sollte. Da Sie den Connected Socket nie erhalten, können Sie nur mit 'accept (2)' syscall von der Socket-Schnittstelle aus eine andere, unprivilegierte Möglichkeit erkennen, dass eine passive Verbindung stattgefunden hat. Per Definition passieren passive Dinge ohne aktive Beteiligung des Prozesses/Threads. Wie kann man also wissen, ob passives Verbinden stattgefunden hat oder nicht? Der Absatz ist die Erklärung für das Problem, auch wenn dies nicht mit der aktiven/passiven Verbindung zusammenhängt. –

+0

@EJP, ja, es gibt einen anderen Weg zu wissen, ob eine Verbindung in der Zeit zwischen 'listen (2)' und 'accept (2)' Systemaufrufen aufgetreten ist: tun Sie ein 'select (2)' zum Einlesen in den hörenden Sockel , aber der Absatz ist nicht falsch, wie Sie sagen. –

Verwandte Themen