Start · Sprachen · PHP · Referenz · stream_socket_recvfrom

stream_socket_recvfrom

Funktion

Empfängt Daten von einem Socket (verbunden oder nicht verbunden) und gibt optional die Absenderadresse zurück.

seit PHP 5.0.0 Kategorie: io

Signatur

stream_socket_recvfrom(resource $socket, int $length, int $flags = 0, string|null &$address = null): string|false

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

Typ
string|false
Beschreibung
Gibt die empfangenen Daten als String zurück, oder 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);
}
UDP-Server lauscht auf Port 1234 ... Empfangen von 127.0.0.1:55123: Hallo Server

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);
Peek: Testpaket Lesen: Testpaket

// 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.