Start · Sprachen · PHP · Referenz · stream_socket_accept

stream_socket_accept

Funktion

Nimmt eine eingehende Verbindung auf einem mit <code>stream_socket_server()</code> erzeugten Server-Socket an und gibt einen Stream zurück.

seit PHP 5.0.0 Kategorie: io

Signatur

stream_socket_accept(resource $server_socket, float $timeout = ini_get('default_socket_timeout'), string &$peername = null): resource|false

Beschreibung

stream_socket_accept() wartet auf eine eingehende Verbindung auf dem übergebenen Server-Socket und gibt bei Erfolg einen neuen Stream-Ressource zurück, über den die Kommunikation mit dem verbundenen Client stattfindet. Der ursprüngliche Server-Socket bleibt dabei weiterhin aktiv und kann für weitere Verbindungen genutzt werden.

Der optionale Parameter $timeout legt fest, wie lange (in Sekunden) auf eine eingehende Verbindung gewartet wird. Läuft das Timeout ab, ohne dass eine Verbindung eingegangen ist, gibt die Funktion false zurück. Ein Wert von 0 bewirkt ein nicht-blockierendes Verhalten, ein negativer Wert wartet unbegrenzt.

Mit dem optionalen Referenzparameter $peername kann die Adresse des verbindenden Clients (z. B. tcp://192.168.1.10:54321) ermittelt werden, was für Logging oder Zugriffskontrolle nützlich ist.

Die Funktion eignet sich besonders für die Implementierung einfacher TCP- oder UDP-Server in PHP, z. B. für Chat-Anwendungen, Protokoll-Proxys oder Test-Server. Für produktive Umgebungen mit hoher Last empfiehlt sich jedoch eine ereignisgesteuerte Architektur (z. B. via stream_select()) oder ein dedizierter Anwendungsserver.

Parameter

Name Typ Default Beschreibung
$server_socket Pflicht resource Ein Server-Socket-Stream, der zuvor mit stream_socket_server() erstellt wurde.
$timeout float ini_get('default_socket_timeout') Zeitlimit in Sekunden, wie lange auf eine eingehende Verbindung gewartet wird. 0 = nicht-blockierend, negativer Wert = unbegrenzt warten.
$peername string null Wird mit der Adresse und dem Port des verbundenen Clients befüllt, z. B. tcp://127.0.0.1:12345. Wird als Referenz übergeben.

Rückgabewert

Typ
resource|false
Beschreibung
Gibt bei erfolgreicher Verbindung eine Stream-Ressource zurück, über die mit dem Client kommuniziert werden kann. Gibt false zurück, wenn das Timeout abläuft, ein Fehler auftritt oder keine Verbindung zustande kommt.

Beispiele

Einfacher TCP-Echo-Server

<?php
// Server-Socket erstellen
$server = stream_socket_server('tcp://0.0.0.0:8080', $errno, $errstr);
if (!$server) {
    die("Fehler beim Erstellen des Sockets: $errstr ($errno)\n");
}

echo "Server lauscht auf Port 8080...\n";

while (true) {
    // Auf eingehende Verbindung warten (max. 30 Sekunden)
    $client = stream_socket_accept($server, 30, $peername);
    if ($client === false) {
        echo "Timeout oder Fehler beim Akzeptieren einer Verbindung.\n";
        continue;
    }

    echo "Verbindung von: $peername\n";

    // Daten vom Client lesen und zurücksenden (Echo)
    $data = fread($client, 1024);
    fwrite($client, "Echo: " . $data);

    fclose($client);
}

fclose($server);
Server lauscht auf Port 8080... Verbindung von: tcp://127.0.0.1:54321

Nicht-blockierender Modus mit stream_select()

<?php
$server = stream_socket_server('tcp://0.0.0.0:9090', $errno, $errstr);
if (!$server) {
    die("Socket-Fehler: $errstr ($errno)\n");
}

stream_set_blocking($server, false);

$clients = [];

while (true) {
    $read = array_merge([$server], $clients);
    $write = null;
    $except = null;

    // Auf Aktivität an einem der Streams warten
    if (stream_select($read, $write, $except, 5) === false) {
        break;
    }

    // Neue Verbindung auf dem Server-Socket?
    if (in_array($server, $read)) {
        $client = stream_socket_accept($server, 0, $peername);
        if ($client !== false) {
            echo "Neuer Client verbunden: $peername\n";
            $clients[] = $client;
        }
        // Server aus der Read-Liste entfernen
        $read = array_filter($read, fn($s) => $s !== $server);
    }

    // Daten von bestehenden Clients lesen
    foreach ($read as $stream) {
        $data = fread($stream, 512);
        if ($data === '' || $data === false) {
            fclose($stream);
            $clients = array_filter($clients, fn($s) => $s !== $stream);
        } else {
            echo "Empfangen: $data\n";
            fwrite($stream, "OK: $data");
        }
    }
}
Neuer Client verbunden: tcp://127.0.0.1:54400 Empfangen: Hallo Server!

// Wichtig · Fallstricke

Sicherheitshinweis: Prüfe die Client-Adresse aus $peername bei sensiblen Anwendungen, um unerwünschte Verbindungen abzulehnen. Verlasse dich dabei jedoch nicht allein auf die IP-Adresse, da diese gefälscht werden kann (IP-Spoofing bei UDP).

Bei der Verwendung von SSL/TLS-Sockets (z. B. ssl://) muss der Server-Socket mit den entsprechenden Zertifikats-Kontextoptionen erstellt werden. stream_socket_accept() führt dann den TLS-Handshake durch.

Im nicht-blockierenden Modus (stream_set_blocking($server, false)) und einem Timeout von 0 kann stream_socket_accept() sofort false zurückgeben, wenn keine Verbindung ansteht — dies ist kein Fehler, sondern erwartetes Verhalten. Nutze stream_select() zur effizienten Überwachung mehrerer Streams.