Signatur
Beschreibung
stream_socket_pair() erstellt zwei miteinander verbundene Socket-Streams, die als vollständiges Kommunikationspaar fungieren. Was in den einen Stream geschrieben wird, kann aus dem anderen gelesen werden – und umgekehrt. Dies ist typisch für Unix-Domain-Sockets (auch als socketpair bekannt).
Die Funktion wird häufig eingesetzt, wenn ein Elternprozess mit einem Kind-Prozess kommunizieren soll, der via pcntl_fork() erzeugt wurde. Jeder Prozess schließt dabei den für ihn nicht benötigten Ende des Paares und verwendet das verbleibende für die Kommunikation.
Der Parameter domain gibt die Protokollfamilie an (z. B. STREAM_PF_UNIX für Unix-Domain-Sockets), type beschreibt den Socket-Typ (z. B. STREAM_SOCK_STREAM für zuverlässige Byte-Streams oder STREAM_SOCK_DGRAM für Datagramme) und protocol legt das Transportprotokoll fest (z. B. STREAM_IPPROTO_IP oder 0 für den Standard).
Zu beachten ist, dass diese Funktion auf Windows-Systemen nicht verfügbar ist, da Windows keine nativen Unix-Domain-Socket-Paare unterstützt. Sie eignet sich daher ausschließlich für POSIX-kompatible Betriebssysteme (Linux, macOS, BSD usw.).
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $domain Pflicht | int | Die Protokollfamilie des Sockets, z. B. STREAM_PF_UNIX für Unix-Domain-Sockets oder STREAM_PF_INET für IPv4. Auf den meisten Systemen wird STREAM_PF_UNIX verwendet. |
|
| $type Pflicht | int | Der Socket-Typ, z. B. STREAM_SOCK_STREAM für einen zuverlässigen, verbindungsorientierten Byte-Stream oder STREAM_SOCK_DGRAM für verbindungslose Datagramme. |
|
| $protocol Pflicht | int | Das zu verwendende Transportprotokoll, z. B. STREAM_IPPROTO_TCP oder 0 (automatische Auswahl). Für Unix-Domain-Sockets wird in der Regel 0 übergeben. |
Rückgabewert
[0] und [1]. Bei einem Fehler wird false zurückgegeben.Beispiele
Einfache bidirektionale Kommunikation zwischen zwei Streams
<?php
// Socket-Paar erstellen
$pair = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, 0);
if ($pair === false) {
die('Konnte kein Socket-Paar erstellen.');
}
[$socket1, $socket2] = $pair;
// Nachricht über socket1 senden
fwrite($socket1, 'Hallo von Socket 1!');
// Nachricht aus socket2 empfangen
$message = fread($socket2, 1024);
echo $message . PHP_EOL;
// Antwort zurücksenden
fwrite($socket2, 'Antwort von Socket 2!');
$reply = fread($socket1, 1024);
echo $reply . PHP_EOL;
fclose($socket1);
fclose($socket2);
Interprozesskommunikation via pcntl_fork()
<?php
if (!function_exists('pcntl_fork')) {
die('pcntl nicht verfügbar.');
}
$pair = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, 0);
if ($pair === false) {
die('Socket-Paar konnte nicht erstellt werden.');
}
$pid = pcntl_fork();
if ($pid === -1) {
die('Fork fehlgeschlagen.');
} elseif ($pid === 0) {
// Kind-Prozess: verwendet socket[1]
fclose($pair[0]);
$data = fread($pair[1], 1024);
echo "Kind empfangen: $data" . PHP_EOL;
fwrite($pair[1], 'Hallo zurück, Eltern!');
fclose($pair[1]);
exit(0);
} else {
// Eltern-Prozess: verwendet socket[0]
fclose($pair[1]);
fwrite($pair[0], 'Hallo, Kind!');
// Kurz warten, damit das Kind antwortet
usleep(50000);
$reply = fread($pair[0], 1024);
echo "Eltern empfangen: $reply" . PHP_EOL;
fclose($pair[0]);
pcntl_wait($status);
}
// Wichtig · Fallstricke
Windows-Inkompatibilität: stream_socket_pair() ist auf Windows-Betriebssystemen nicht verfügbar. Wer plattformübergreifenden Code schreiben möchte, muss auf Alternativen wie stream_socket_server()/stream_socket_client() mit TCP-Loopback ausweichen.
Ressourcen schließen: In einer Fork-Umgebung ist es wichtig, den jeweils nicht benötigten Stream-Endpunkt im entsprechenden Prozess sofort mit fclose() zu schließen, um Deadlocks und unerwartetes Blockieren beim Lesen zu vermeiden.
Blockierendes I/O: Standardmäßig sind die zurückgegebenen Streams blockierend. Mit stream_set_blocking() kann auf nicht-blockierenden Modus umgestellt werden, falls asynchrones Lesen/Schreiben benötigt wird.