Signatur
Beschreibung
socket_accept() wartet auf eine eingehende Verbindung an einem zuvor mit socket_bind() und socket_listen() vorbereiteten Socket. Sobald ein Client eine Verbindung aufbaut, gibt die Funktion einen neuen Socket-Ressource zurück, der ausschließlich für die Kommunikation mit diesem Client verwendet wird. Der ursprüngliche Server-Socket bleibt unverändert und kann weiterhin auf weitere Verbindungen warten.
Die Funktion arbeitet standardmäßig blockierend: Sie hält die Ausführung des Skripts an, bis eine Verbindung eingeht. Mit socket_set_nonblock() oder socket_set_block() lässt sich das Verhalten steuern. Im nicht-blockierenden Modus gibt die Funktion sofort false zurück, wenn keine Verbindung ansteht.
Das typische Anwendungsmuster für einen TCP-Server lautet: Socket erstellen → binden → lauschen → in einer Schleife socket_accept() aufrufen → mit dem zurückgegebenen Client-Socket Daten lesen/schreiben → Client-Socket schließen. Der zurückgegebene Socket muss nach Gebrauch explizit mit socket_close() geschlossen werden, um Ressourcen freizugeben.
Für produktive Server-Anwendungen mit vielen gleichzeitigen Verbindungen empfiehlt sich der Einsatz von socket_select(), um mehrere Sockets gleichzeitig zu überwachen, oder der Wechsel zu asynchronen Frameworks wie ReactPHP oder Swoole.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $socket Pflicht | Socket | Ein gültiger, lauschender Socket-Ressource, der zuvor mit socket_create(), socket_bind() und socket_listen() vorbereitet wurde. |
Rückgabewert
Socket-Objekt zurückgegeben, das die Verbindung zum verbundenen Client repräsentiert. Im Fehlerfall (z. B. ungültiger Socket oder nicht-blockierender Modus ohne ausstehende Verbindung) wird false zurückgegeben. Fehlercodes können mit socket_last_error() abgerufen werden.Beispiele
Einfacher TCP-Echo-Server
<?php
// Socket erstellen (IPv4, TCP)
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($server === false) {
die('socket_create() fehlgeschlagen: ' . socket_strerror(socket_last_error()));
}
// Socket an Adresse und Port binden
socket_bind($server, '127.0.0.1', 8080);
// Auf eingehende Verbindungen lauschen (max. 5 in der Warteschlange)
socket_listen($server, 5);
echo "Server lauscht auf 127.0.0.1:8080 ...\n";
while (true) {
// Blockierend warten, bis ein Client verbindet
$client = socket_accept($server);
if ($client === false) {
echo 'socket_accept() fehlgeschlagen: ' . socket_strerror(socket_last_error($server)) . "\n";
continue;
}
// Begrüßungsnachricht senden
$message = "Willkommen beim Echo-Server!\n";
socket_write($client, $message, strlen($message));
// Daten vom Client lesen
$input = socket_read($client, 1024, PHP_NORMAL_READ);
$input = trim($input);
echo "Empfangen: $input\n";
// Eingabe zurückspiegeln (Echo)
$response = "Echo: $input\n";
socket_write($client, $response, strlen($response));
// Client-Socket schließen
socket_close($client);
// Nach einer Anfrage beenden (Demo-Zweck)
break;
}
socket_close($server);
echo "Server beendet.\n";
Nicht-blockierender Accept mit socket_select()
<?php
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($server, '127.0.0.1', 9090);
socket_listen($server, 10);
// Nicht-blockierenden Modus aktivieren
socket_set_nonblock($server);
$clients = [];
$running = true;
echo "Nicht-blockierender Server auf Port 9090 gestartet.\n";
// Simulierte Schleife (in der Praxis z. B. zeitlich begrenzt)
$iterations = 0;
while ($running && $iterations < 100) {
$iterations++;
// socket_select() prüft, ob Aktivität auf dem Server-Socket vorliegt
$read = array_merge([$server], $clients);
$write = $except = [];
$changed = socket_select($read, $write, $except, 0, 200000); // 200 ms Timeout
if ($changed === false) {
break;
}
// Neue Verbindung prüfen
if (in_array($server, $read)) {
$client = socket_accept($server);
if ($client !== false) {
$clients[] = $client;
socket_write($client, "Verbunden!\n");
echo "Neuer Client verbunden.\n";
}
}
// Daten von bestehenden Clients lesen
foreach ($clients as $key => $sock) {
if (in_array($sock, $read)) {
$data = @socket_read($sock, 1024, PHP_NORMAL_READ);
if ($data === false || $data === '') {
socket_close($sock);
unset($clients[$key]);
echo "Client getrennt.\n";
} else {
echo "Daten: " . trim($data) . "\n";
}
}
}
}
foreach ($clients as $sock) {
socket_close($sock);
}
socket_close($server);
echo "Server gestoppt.\n";
// Wichtig · Fallstricke
Sicherheitshinweis: Validiere stets die Herkunft eingehender Verbindungen mit socket_getpeername(), wenn nur bestimmte IP-Adressen zugelassen werden sollen. Ohne Filterung kann jeder Client eine Verbindung aufbauen.
Ressourcen-Verwaltung: Jeder von socket_accept() zurückgegebene Client-Socket muss nach Gebrauch mit socket_close() geschlossen werden, sonst entstehen Ressourcen-Lecks (Dateideskriptoren).
Hinweis zu PHP-Versionen: Seit PHP 8.0 wird statt einer Ressource ein Socket-Objekt zurückgegeben. Code, der is_resource() zur Prüfung verwendet, muss für PHP 8+ angepasst werden.
Blockierendes Verhalten: Im blockierenden Modus kann das Skript unendlich lange anhalten, wenn keine Verbindung eingeht. Für robuste Server sollte socket_select() mit Timeout verwendet werden.