Start · Sprachen · PHP · Referenz · socket_shutdown

socket_shutdown

Funktion

Schließt einen Socket für das Senden, Empfangen oder beides und signalisiert dem Gegenstück das Ende der Kommunikation.

seit PHP 4.1.0 Kategorie: http

Signatur

socket_shutdown(Socket $socket, int $mode = 2): bool

Beschreibung

socket_shutdown() beendet die Kommunikation über einen Socket in eine oder beide Richtungen, ohne die zugrundeliegende Socket-Ressource sofort freizugeben. Damit kann ein Halbschluss (half-close) realisiert werden: Der Server kann z. B. das Senden einstellen, aber weiterhin Daten empfangen – oder umgekehrt.

Der Parameter mode steuert, welche Richtung geschlossen wird: 0 deaktiviert das Empfangen, 1 deaktiviert das Senden und 2 (Standard) beendet beides. Erst nach socket_shutdown() sollte socket_close() aufgerufen werden, um die Ressource endgültig freizugeben.

Typischer Einsatz ist das saubere Beenden einer TCP-Verbindung: Der Client sendet alle Daten, ruft dann socket_shutdown($sock, 1) auf (FIN senden), liest noch verbleibende Antworten und ruft schließlich socket_close() auf. Dieses Vorgehen vermeidet abrupt abgebrochene Verbindungen (RST) und Datenverlust.

Zu beachten ist, dass socket_shutdown() nicht mit fclose() auf Stream-Sockets (erzeugt via stream_socket_client()) kombiniert werden kann; es arbeitet ausschließlich mit Socket-Objekten, die durch socket_create() oder socket_accept() erzeugt wurden.

Parameter

Name Typ Default Beschreibung
$socket Pflicht Socket Ein gültiges Socket-Objekt, das zuvor mit socket_create() oder socket_accept() erzeugt und verbunden wurde.
$mode int 2 Bestimmt die Richtung des Halbschlusses: 0 = Empfangen deaktivieren, 1 = Senden deaktivieren, 2 = beides deaktivieren (Standardwert).

Rückgabewert

Typ
bool
Beschreibung
Gibt true bei Erfolg zurück, false bei einem Fehler. Im Fehlerfall kann mit socket_last_error() und socket_strerror() die Fehlerursache ermittelt werden.

Beispiele

Sauberes Beenden einer TCP-Client-Verbindung

<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
    die('socket_create() fehlgeschlagen: ' . socket_strerror(socket_last_error()));
}

if (!socket_connect($socket, '127.0.0.1', 8080)) {
    die('socket_connect() fehlgeschlagen: ' . socket_strerror(socket_last_error($socket)));
}

$request = "GET / HTTP/1.0\r\nHost: 127.0.0.1\r\nConnection: close\r\n\r\n";
socket_write($socket, $request, strlen($request));

// Senden abschließen (FIN senden), Empfangen noch erlaubt
socket_shutdown($socket, 1);

// Verbleibende Antwort lesen
$response = '';
while ($chunk = socket_read($socket, 2048)) {
    $response .= $chunk;
}

echo $response;

// Socket vollständig freigeben
socket_shutdown($socket, 0);
socket_close($socket);

Halbschluss auf Server-Seite nach dem Senden der Antwort

<?php
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($server, '0.0.0.0', 9000);
socket_listen($server, 5);

echo "Server wartet auf Port 9000...\n";

$client = socket_accept($server);
if ($client !== false) {
    $data = socket_read($client, 1024);
    echo "Empfangen: " . trim($data) . "\n";

    $antwort = "Hallo, Client! Verbindung wird sauber beendet.\n";
    socket_write($client, $antwort, strlen($antwort));

    // Nur Senden beenden; Client kann noch senden, falls nötig
    socket_shutdown($client, 1);

    // Danach alles schließen
    socket_shutdown($client, 0);
    socket_close($client);
}

socket_close($server);
Server wartet auf Port 9000...

// Wichtig · Fallstricke

Reihenfolge beachten: socket_shutdown() sollte stets vor socket_close() aufgerufen werden. Ein direktes socket_close() ohne vorheriges Shutdown kann dazu führen, dass gepufferte Daten verloren gehen und die Gegenseite eine unerwartete RST-Verbindungstrennung erhält.

Ressourcen-Typ: Ab PHP 8.0 erwartet die Funktion ein Socket-Objekt statt einer alten resource. Code, der noch mit resource arbeitet, muss für PHP 8+ angepasst werden.

Nicht-blockierende Sockets: Bei nicht-blockierenden Sockets kann socket_shutdown() ebenfalls verwendet werden; es ist jedoch zu beachten, dass ausstehende Lesevorgänge durch den Halbschluss in Modus 0 abgebrochen werden.