In den Domänen AF_INET und AF_INET6 kann eine Verbindung wahlweise mit soc_close() oder shutdown() abgebaut werden. Das Schließen eines Sockets ist nur mit soc_close(), nicht jedoch mit shutdown() möglich.
Beim Verbindungsabbau wird unterschieden zwischen „graceful disconnect“ und „abortive disconnect“. Die spezifische Behandlung erfolgt durch das Transportsystem bzw. durch die TCP-Protokollmaschine. Mit den Funktionen soc_close() und shutdown() wird eine der beiden Möglichkeiten ausgewählt.
Die nachfolgenden Erläuterungen des Verbindungsabbaus mit soc_close() und shutdown() basieren auf der in Bild 2 skizzierten Situation. Es soll eine Client-/Server-Verbindung abgebaut werden, über die in beiden Richtungen Daten transferiert wurden.
Bild 2: Client-/Server-Verbindung mit bidirektionalem Datentransfer
Verbindungsabbau („graceful“) mit soc_close()
Im Einzelnen werden folgende Schritte ausgeführt:
Nach dem Senden der letzten Daten leitet der Server S mit soc_close() auf den Socket von S den Verbindungsabbau ein. Dadurch wird der betroffene Socket von S für das Schreiben gesperrt, und dem Partner-Socket im Client C wird signalisiert, dass der Socket von S keine Daten mehr senden wird. Dies entspricht einem „graceful disconnect“. Nach einem „graceful disconnect“ wird die Verbindung zwar noch aufrecht erhalten, aber die Datenübertragung von S nach C ist gesperrt.
Nach Empfang des Signals für „graceful disconnect“ kann das Anwenderprogramm des Clients C alle noch nicht abgeholten Daten lesen, bis mit EOF das Ende des Datenstroms angezeigt wird.
Der Client C ruft soc_close() für den Socket von C auf. Dadurch wird an S ein „graceful disconnect“ gesendet und die Verbindung vollständig abgebaut. In C wird der Socket geschlossen. In S wird der Verbindungsabbau signalisiert und der Socket geschlossen.
Falls C auf das „graceful disconnect“-Ereignis mit einem Aufruf von soc_close() antwortet, ohne vorher zu versuchen, eventuell noch vorhandene Daten zu lesen, dann wird die Verbindung sofort vollständig abgebaut und Datenverlust ist die Folge.
Verbindungsabbau („graceful“) mit shutdown()
Im Einzelnen werden folgende Schritte ausgeführt:
Nach dem Senden der letzten Daten leitet der Server S mit shutdown(... , SHUT_WR) auf den Socket von S den Verbindungsabbau ein. Dadurch wird der betroffene Socket von S für das Schreiben gesperrt, und dem Partner-Socket im Client C wird signalisiert, dass der Socket von S keine Daten mehr senden wird. Dies entspricht einem „graceful disconnect“. Nach einem „graceful disconnect“ wird die Verbindung zwar noch aufrecht erhalten, aber die Datenübertragung von S nach C ist gesperrt.
Nach Empfang des Signals für „graceful disconnect“ kann das Anwenderprogramm des Clients C alle noch nicht abgeholten Daten lesen, bis mit EOF das Ende des Datenstroms angezeigt wird.
Der Client C ruft shutdown(... , SHUT_WR) für den Socket von C auf. Dadurch wird an S ein „graceful disconnect“ gesendet und die Verbindung vollständig abgebaut.
Die Sockets in S und C werden jeweils mit soc_close() geschlossen.
Falls C auf das „graceful disconnect“-Ereignis mit einem Aufruf shutdown(... ,SHUT_WR) antwortet, ohne vorher zu versuchen, eventuell noch vorhandene Daten zu lesen, wird die Verbindung sofort vollständig abgebaut und Datenverlust ist die Folge.
Verbindungsabbau („abortive“) mit soc_close()
Im Einzelnen werden folgende Schritte ausgeführt:
Der Server S markiert seine Socket-Schnittstelle mit der Option SO_LINGER der Funktion setsockopt() und setzt das Verzögerungsintervall l_linger in der Struktur linger auf 0.
Wenn der Server die Funktion soc_close() aufruft, wird der Verbindungsabbau „abortive“ eingeleitet. Auf den Socket von S ist jetzt weder Schreiben noch Lesen möglich. Dem Partner-Socket in Client C wird der „abortive disconnect“ signalisiert, und der Socket im Server S wird geschlossen.
Nach dem Empfang des Signals „abortive disconnect“ kann das Anwenderprogramm im Client C keine Daten mehr lesen. Eventuell vorhandene, aber noch nicht aus dem Transportsystem abgeholte Daten sind verloren.
Der Client C kann deshalb nur mit soc_close() auf den Socket in S reagieren und damit den Socket in C schließen.
Verbindungsabbau („abortive“) mit shutdown()
Im Einzelnen werden folgende Schritte ausgeführt:
Der Server S leitet den Verbindungsabbau mit shutdown(..., SHUT_RDWR) ein. Auf dem Socket ist jetzt weder Schreiben noch Lesen möglich, und der Partner-Socket im Client C wird über den „abortive disconnect“ informiert.
Wenn das Anwendungsprogramm im Client C vor dem Empfang von „abortive disconnect“ eventuell vorhandene Daten vom Transportsystem nicht abgeholt hat, sind diese jetzt verloren.
Daher ist es nur sinnvoll, im Client C mit shutdown(...,SHUT_RDWR) zu antworten und die Sockets im Server S und Client C jeweils mit soc_close() zu schließen.