Signatur
Beschreibung
stream_select() überwacht eine Gruppe von Streams auf Aktivität und wartet, bis mindestens einer davon bereit ist oder ein Timeout abläuft. Das Prinzip entspricht dem POSIX-select()-Systemaufruf: Es können gleichzeitig Streams auf Lesbarkeit ($read), Schreibbereitschaft ($write) und Ausnahmezustände ($except) geprüft werden.
Nach dem Aufruf werden die Arrays in-place modifiziert – sie enthalten nur noch die Streams, die tatsächlich aktiv sind. Nicht aktive Streams werden aus den Arrays entfernt. Dies ermöglicht nicht-blockierendes I/O ohne Threads: Man kann in einer einzigen Schleife viele Netzwerk- oder Datei-Streams bedienen.
Ein Timeout von null bei $seconds bewirkt, dass stream_select() unbegrenzt blockiert, bis ein Stream aktiv wird. Ein Timeout von 0 (und $microseconds = 0) führt zu einem sofortigen Poll ohne Wartezeit. Diese Funktion eignet sich besonders für Multiplexing von Socket-Verbindungen, Chat-Server, Proxys oder jede Situation, in der mehrere Datenquellen gleichzeitig bedient werden müssen.
Streams können mit stream_socket_client(), stream_socket_server(), fsockopen() oder fopen() erstellt werden. STDIN, STDOUT und STDERR können ebenfalls verwendet werden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $read Pflicht | array | Array von Streams, die auf Lesbarkeit überwacht werden sollen. Nach dem Aufruf enthält das Array nur noch die lesbaren Streams. Zum Ignorieren [] oder null übergeben. |
|
| $write Pflicht | array|null | Array von Streams, die auf Schreibbereitschaft überwacht werden sollen. Nach dem Aufruf enthält das Array nur noch die schreibbereiten Streams. Kann null sein, wenn Schreibbereitschaft nicht geprüft werden soll. |
|
| $except Pflicht | array|null | Array von Streams, die auf Ausnahmezustände (z. B. Out-of-band-Daten bei TCP-Sockets) überwacht werden sollen. In der Praxis selten benötigt; kann null sein. |
|
| $seconds Pflicht | int|null | Timeout-Sekunden. null bedeutet unbegrenztes Warten; 0 bedeutet sofortiger Poll (kein Warten). Muss zusammen mit $microseconds angegeben werden. |
|
| $microseconds | int | 0 | Zusätzliche Mikrosekunden zum Timeout. Ermöglicht feinere Timeout-Auflösung unterhalb einer Sekunde. |
Rückgabewert
0 zurück, wenn der Timeout abgelaufen ist, ohne dass ein Stream aktiv wurde. Gibt false zurück bei einem Fehler (z. B. wenn alle drei Arrays leer oder null sind, oder bei einem Systemfehler).Beispiele
Mehrere Sockets gleichzeitig auf eingehende Daten überwachen
<?php
// Zwei nicht-blockierende Verbindungen aufbauen
$sock1 = stream_socket_client('tcp://example.com:80', $errno1, $errstr1, 5);
$sock2 = stream_socket_client('tcp://example.org:80', $errno2, $errstr2, 5);
if (!$sock1 || !$sock2) {
die('Verbindung fehlgeschlagen');
}
// HTTP-Anfragen absenden
fwrite($sock1, "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n");
fwrite($sock2, "GET / HTTP/1.0\r\nHost: example.org\r\n\r\n");
$streams = [$sock1, $sock2];
while (!empty($streams)) {
$read = $streams;
$write = null;
$except = null;
// Bis zu 5 Sekunden auf Aktivität warten
$ready = stream_select($read, $write, $except, 5);
if ($ready === false) {
echo "Fehler bei stream_select()\n";
break;
}
if ($ready === 0) {
echo "Timeout: Keine Antwort innerhalb von 5 Sekunden.\n";
break;
}
// Nur aktive Streams verarbeiten
foreach ($read as $stream) {
$data = fread($stream, 1024);
if ($data === '' || $data === false || feof($stream)) {
// Stream ist geschlossen — aus Überwachungsliste entfernen
$key = array_search($stream, $streams, true);
if ($key !== false) {
unset($streams[$key]);
}
fclose($stream);
} else {
echo "Daten empfangen (". strlen($data) ." Bytes)\n";
}
}
}
?>
Nicht-blockierender Poll (sofortiger Timeout = 0)
<?php
// Stream öffnen (z. B. STDIN in einer CLI-Anwendung)
$read = [STDIN];
$write = null;
$except = null;
// Sofortige Prüfung ohne zu warten (timeout = 0)
$ready = stream_select($read, $write, $except, 0, 0);
if ($ready > 0) {
$line = fgets(STDIN);
echo 'Eingabe erkannt: ' . $line;
} else {
echo "Keine Eingabe vorhanden (nicht blockierend).\n";
}
?>
// Wichtig · Fallstricke
Wichtig: Alle drei Array-Parameter werden als Referenz übergeben und verändert. Wenn du die originalen Stream-Listen benötigst, musst du sie vor dem Aufruf kopieren (z. B. $read = $meineStreams;).
Signal-Unterbrechung: Unter Unix kann stream_select() durch ein Signal (z. B. SIGCHLD) unterbrochen werden und false zurückgeben, obwohl kein Fehler vorliegt. In solchen Fällen sollte false nicht als fataler Fehler behandelt werden, wenn stream_select() in einer Schleife läuft.
Windows-Einschränkung: Unter Windows können nur Sockets überwacht werden — reguläre Datei-Handles und Pipes funktionieren möglicherweise nicht korrekt mit stream_select().
Leere Arrays: Wenn alle drei Arrays leer oder null sind, gibt die Funktion false zurück und erzeugt eine Warnung. Mindestens ein Stream muss übergeben werden.