Signatur
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
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);
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");
}
}
}
// 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.