Signatur
Beschreibung
PHP-Streams, die über TCP, UDP oder andere Socket-Protokolle kommunizieren, können über sogenannte Socket-Kontextoptionen feinkonfiguriert werden. Diese Optionen werden beim Erstellen eines Stream-Kontexts mit stream_context_create() im Schlüssel 'socket' übergeben und beeinflussen, wie der zugrundeliegende Socket konfiguriert und geöffnet wird.
Typische Anwendungsfälle sind das Binden an eine bestimmte lokale IP-Adresse oder einen lokalen Port vor dem Verbindungsaufbau (bindto), das Aktivieren von TCP Keep-Alive-Paketen (tcp_nodelay) oder das Setzen von Socket-Optionen wie SO_REUSEPORT. Dies ist besonders nützlich in Netzwerkanwendungen, die über mehrere Netzwerkinterfaces verfügen oder spezifische Routing-Anforderungen haben.
Die Optionen gelten für alle Stream-Wrapper, die intern Sockets verwenden, also z. B. tcp://, udp://, ssl:// und http:// (sofern dieser einen Socket öffnet). Der Kontext wird dann an Funktionen wie stream_socket_client(), fsockopen() oder fopen() übergeben.
- bindto (
string): Lokale IP-Adresse und optionaler Port, an den der Socket gebunden wird, z. B.'192.168.1.10:0'oder'[::]:0'für IPv6. - backlog (
int): Setzt die Länge der Warteschlange für eingehende Verbindungen (nur serverseitig). - ipv6_v6only (
bool): Erzwingt IPv6-only-Sockets, ohne IPv4-Kompatibilität. - so_reuseport (
bool): Erlaubt mehreren Prozessen, denselben Port zu verwenden (sofern OS dies unterstützt). - so_broadcast (
bool): Aktiviert das Senden an Broadcast-Adressen. - tcp_nodelay (
bool): Deaktiviert den Nagle-Algorithmus für geringere Latenz.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $options | array | [] | Assoziatives Array mit Kontextoptionen, z. B. ['socket' => ['bindto' => '192.168.1.1:0', 'tcp_nodelay' => true]]. |
| $params | array | [] | Optionale Stream-Parameter, z. B. Callback-Funktionen für Benachrichtigungen. |
Rückgabewert
stream_socket_client() oder fopen() übergeben werden kann.Beispiele
HTTP-Anfrage über eine bestimmte lokale IP-Adresse senden
<?php
// Kontext erstellen, der den Socket an eine bestimmte lokale IP bindet
$context = stream_context_create([
'socket' => [
'bindto' => '192.168.1.10:0', // lokale IP, Port 0 = automatisch
],
'http' => [
'method' => 'GET',
'header' => 'Accept: text/html',
],
]);
$response = file_get_contents('http://example.com', false, $context);
if ($response !== false) {
echo 'Antwort erhalten, Länge: ' . strlen($response) . ' Bytes';
} else {
echo 'Verbindung fehlgeschlagen';
}
TCP-Verbindung mit tcp_nodelay und bindto aufbauen
<?php
// Socket-Kontext mit deaktiviertem Nagle-Algorithmus
$context = stream_context_create([
'socket' => [
'tcp_nodelay' => true,
'bindto' => '0.0.0.0:0', // alle Interfaces, automatischer Port
],
]);
$errno = 0;
$errstr = '';
$socket = stream_socket_client(
'tcp://example.com:80',
$errno,
$errstr,
30,
STREAM_CLIENT_CONNECT,
$context
);
if ($socket === false) {
echo "Fehler ($errno): $errstr";
} else {
fwrite($socket, "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n");
$response = fread($socket, 512);
fclose($socket);
echo 'Erste 512 Bytes empfangen: ' . PHP_EOL . $response;
}
Server-Socket mit so_reuseport für mehrere Prozesse
<?php
// Erlaubt mehreren Worker-Prozessen, denselben Port zu öffnen
$context = stream_context_create([
'socket' => [
'so_reuseport' => true,
'backlog' => 128,
],
]);
$server = stream_socket_server(
'tcp://0.0.0.0:8080',
$errno,
$errstr,
STREAM_SERVER_BIND | STREAM_SERVER_LISTEN,
$context
);
if ($server === false) {
die("Server-Start fehlgeschlagen ($errno): $errstr");
}
echo 'Server lauscht auf Port 8080 ...' . PHP_EOL;
// ... hier würde die Accept-Schleife folgen
fclose($server);
// Wichtig · Fallstricke
Plattformabhängigkeit: Nicht alle Socket-Optionen stehen auf jedem Betriebssystem zur Verfügung. so_reuseport wird z. B. unter Windows nicht vollständig unterstützt. Prüfen Sie die OS-Dokumentation für Einzelheiten.
bindto und IPv6: Für IPv6-Adressen muss die Adresse in eckigen Klammern angegeben werden, z. B. '[::1]:0'. Fehlt die korrekte Formatierung, schlägt das Binden still fehl.
Sicherheit: Das Binden an 0.0.0.0 oder :: öffnet den Socket auf allen Netzwerkinterfaces — in Produktionsumgebungen sollte stets nur das notwendige Interface gebunden werden, um die Angriffsfläche zu minimieren.