Signatur
Beschreibung
stream_socket_recvfrom() liest bis zu $length Bytes von einem Socket-Stream. Im Gegensatz zu fread() erlaubt diese Funktion auch das Empfangen von Datagrammen über nicht verbundene Sockets (z. B. UDP), da sie die Absenderadresse in $address zurückschreiben kann.
Besonders nützlich ist die Funktion beim Bau von UDP-Servern oder -Clients: Man kann mehrere Pakete von verschiedenen Absendern empfangen und anhand der zurückgelieferten Adresse gezielt antworten. Bei verbundenen TCP-Streams verhält sich die Funktion ähnlich wie fread(), bietet aber zusätzlich die Möglichkeit, das STREAM_OOB-Flag für Out-of-Band-Daten zu nutzen.
Über den Parameter $flags lassen sich zwei Verhalten steuern: STREAM_OOB liest Out-of-Band-Daten (dringende TCP-Daten) und STREAM_PEEK liest Daten, ohne den Puffer zu leeren — der nächste Leseaufruf liefert dieselben Daten erneut.
Die Funktion blockiert standardmäßig, bis Daten verfügbar sind. Um nicht-blockierendes Verhalten zu erzielen, kann der Socket zuvor mit stream_set_blocking() in den nicht-blockierenden Modus versetzt werden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $socket Pflicht | resource | Ein Socket-Stream-Ressource, wie er z. B. von stream_socket_server() oder stream_socket_client() erstellt wurde. |
|
| $length Pflicht | int | Maximale Anzahl von Bytes, die empfangen werden sollen. Bei UDP-Datagrammen sollte dieser Wert mindestens der maximalen Paketgröße entsprechen, da überzählige Bytes verworfen werden. | |
| $flags | int | 0 | Optionale Flags als OR-Kombination: STREAM_OOB zum Lesen von Out-of-Band-Daten und STREAM_PEEK zum Lesen ohne Puffer-Verbrauch. |
| $address | string|null | null | Wird als Referenz übergeben. Nach dem Aufruf enthält diese Variable die Absenderadresse im Format ip:port (z. B. 192.168.1.1:54321) oder den Pfad bei Unix-Domain-Sockets. Wird null übergeben, wird die Adresse nicht ermittelt. |
Rückgabewert
false bei einem Fehler. Im nicht-blockierenden Modus kann auch ein leerer String zurückgegeben werden, wenn keine Daten verfügbar sind.Beispiele
Einfacher UDP-Server, der Pakete empfängt und beantwortet
<?php
// UDP-Server auf Port 1234 starten
$server = stream_socket_server('udp://0.0.0.0:1234', $errno, $errstr, STREAM_SERVER_BIND);
if (!$server) {
die("Fehler $errno: $errstr");
}
echo "UDP-Server lauscht auf Port 1234 ...\n";
while (true) {
// Bis zu 1024 Bytes empfangen, Absenderadresse in $from speichern
$data = stream_socket_recvfrom($server, 1024, 0, $from);
if ($data === false) {
echo "Fehler beim Empfangen.\n";
continue;
}
echo "Empfangen von $from: $data\n";
// Antwort an den Absender senden
stream_socket_sendto($server, "ACK: $data", 0, $from);
}
STREAM_PEEK — Daten lesen ohne Puffer zu leeren
<?php
$client = stream_socket_client('udp://127.0.0.1:1234', $errno, $errstr);
if (!$client) {
die("Verbindung fehlgeschlagen: $errstr");
}
// Daten senden
fwrite($client, 'Testpaket');
// Ersten Blick ohne Puffer-Verbrauch
$peek = stream_socket_recvfrom($client, 1024, STREAM_PEEK, $addr);
echo "Peek: $peek\n"; // Daten im Puffer
// Nochmaliges Lesen liefert dieselben Daten
$data = stream_socket_recvfrom($client, 1024, 0, $addr);
echo "Lesen: $data\n"; // Daten wurden jetzt aus dem Puffer entfernt
fclose($client);
// Wichtig · Fallstricke
Puffergröße bei UDP: Wenn $length kleiner als die tatsächliche Paketgröße ist, werden die überzähligen Bytes verworfen — es gibt keinen zweiten Leseaufruf, um den Rest zu erhalten. Wähle $length daher groß genug für das maximale erwartete Datagramm (üblicherweise 65535 Bytes).
Blockierendes Verhalten: Standardmäßig blockiert der Aufruf, bis Daten eintreffen. Nutze stream_set_blocking($socket, false) oder stream_select(), um mehrere Sockets gleichzeitig zu überwachen und Deadlocks zu vermeiden.
Sicherheit: Validiere eingehende Daten und die Absenderadresse immer sorgfältig, bevor du auf Basis dieser Informationen Aktionen ausführst, um Angriffe wie IP-Spoofing oder Buffer-Overflow-Versuche abzuwehren.