Signatur
Beschreibung
stream_socket_server() öffnet einen Server-Socket für das angegebene Protokoll (TCP, UDP, Unix-Domain-Socket etc.) und bindet ihn an die übergebene Adresse. Die Funktion ist die moderne, stream-basierte Alternative zu socket_create() und integriert sich nahtlos in PHPs Stream-Wrapper-System.
Die Adresse folgt dem Schema transport://host:port, z. B. tcp://0.0.0.0:8080, udp://127.0.0.1:5353 oder unix:///tmp/app.sock. Für TLS/SSL-Verbindungen werden die Kontextoptionen über einen Stream-Kontext (stream_context_create()) übergeben.
Mit dem Parameter $flags lässt sich steuern, ob nur gebunden (STREAM_SERVER_BIND) oder zusätzlich auf Verbindungen gehorcht wird (STREAM_SERVER_LISTEN). Bei UDP-Sockets sollte STREAM_SERVER_BIND ohne STREAM_SERVER_LISTEN verwendet werden, da UDP verbindungslos ist.
Nach erfolgreichem Aufruf können mit stream_socket_accept() eingehende Verbindungen angenommen werden. Die zurückgegebene Ressource sollte nach Gebrauch mit fclose() geschlossen werden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $address Pflicht | string | Die Adresse des Sockets im Format transport://host:port, z. B. tcp://0.0.0.0:8080 oder unix:///var/run/app.sock. |
|
| $error_code | int | null | Wird bei einem Fehler mit dem systemspezifischen Fehlercode befüllt (by reference). Bleibt 0, wenn kein Fehler aufgetreten ist. |
| $error_message | string | null | Wird bei einem Fehler mit der zugehörigen Fehlermeldung als Zeichenkette befüllt (by reference). |
| $flags | int | STREAM_SERVER_BIND | STREAM_SERVER_LISTEN | Bitmaske aus STREAM_SERVER_BIND und/oder STREAM_SERVER_LISTEN. Für UDP sollte nur STREAM_SERVER_BIND gesetzt werden. |
| $context | resource|null | null | Optionaler Stream-Kontext, der z. B. SSL-Zertifikat und -Schlüssel für TLS-Server-Sockets enthält. Wird mit stream_context_create() erzeugt. |
Rückgabewert
false zurückgegeben und $error_code sowie $error_message werden befüllt.Beispiele
Einfacher TCP-Echo-Server
<?php
$address = 'tcp://127.0.0.1:9000';
$server = stream_socket_server($address, $errno, $errstr);
if ($server === false) {
die("Konnte Socket nicht öffnen: [$errno] $errstr\n");
}
echo "Server lauscht auf $address ...\n";
while ($client = stream_socket_accept($server, 30)) {
$data = fread($client, 1024);
echo "Empfangen: $data";
fwrite($client, "Echo: " . $data);
fclose($client);
}
fclose($server);
TLS-Server-Socket mit Stream-Kontext
<?php
$context = stream_context_create([
'ssl' => [
'local_cert' => '/etc/ssl/certs/server.pem',
'local_pk' => '/etc/ssl/private/server.key',
'allow_self_signed' => true,
'verify_peer' => false,
],
]);
$server = stream_socket_server(
'tls://0.0.0.0:4430',
$errno,
$errstr,
STREAM_SERVER_BIND | STREAM_SERVER_LISTEN,
$context
);
if ($server === false) {
die("TLS-Server-Fehler [$errno]: $errstr\n");
}
echo "TLS-Server gestartet auf Port 4430\n";
while ($client = stream_socket_accept($server, 60, $peer)) {
echo "Verbindung von: $peer\n";
fwrite($client, "Willkommen beim sicheren Server!\r\n");
fclose($client);
}
fclose($server);
UDP-Socket (nur binden, kein listen)
<?php
$server = stream_socket_server(
'udp://127.0.0.1:5000',
$errno,
$errstr,
STREAM_SERVER_BIND
);
if ($server === false) {
die("UDP-Fehler [$errno]: $errstr\n");
}
echo "UDP-Socket bereit auf Port 5000\n";
// Datagramm empfangen
$data = stream_socket_recvfrom($server, 512, 0, $peer);
echo "Paket von $peer: $data\n";
fclose($server);
// Wichtig · Fallstricke
Sicherheit: Binde Server-Sockets niemals unnötigerweise an 0.0.0.0 (alle Schnittstellen), wenn der Dienst nur lokal erreichbar sein soll. Verwende stattdessen 127.0.0.1.
Blockierendes vs. nicht-blockierendes I/O: Standardmäßig ist der Socket blockierend. Mit stream_set_blocking($server, false) kann er in den nicht-blockierenden Modus versetzt werden, was für Event-Loops (z. B. in Kombination mit stream_select()) notwendig ist.
Unix-Domain-Sockets: Bei unix://-Sockets bleibt die Socket-Datei nach Programmende erhalten. Sie sollte im Aufräum-Code explizit mit unlink() gelöscht werden.
Port-Privilegien: Ports unter 1024 erfordern unter Linux/Unix Root-Rechte oder entsprechende Capabilities (CAP_NET_BIND_SERVICE). Für Produktivumgebungen empfiehlt sich ein Reverse-Proxy wie nginx.