Signatur
Beschreibung
socket_recvmsg() ist die PHP-Entsprechung des POSIX-Systemaufrufs recvmsg(2). Sie liest eine vollständige Nachricht von einem Socket und gibt neben dem eigentlichen Nutzdaten-Puffer auch Metainformationen wie die Absenderadresse und sogenannte Ancillary-Data (z. B. übergebene Dateideskriptoren oder Credentials) zurück. Das Ergebnis wird direkt in das per Referenz übergebene $message-Array geschrieben.
Die Funktion eignet sich besonders für Unix-Domain-Sockets, wenn File-Descriptor-Passing oder Prozess-Authentifizierung (SCM_CREDENTIALS) benötigt wird, sowie für UDP-Sockets, bei denen pro Empfangsaufruf genau eine Datagramm-Einheit verarbeitet werden soll. Im Gegensatz zu socket_recv() liefert socket_recvmsg() strukturierte Steuerinformationen.
Das $message-Array muss vor dem Aufruf mit den Schlüsseln name (Puffer für die Absenderadresse), iov (Array von I/O-Vektoren als Empfangspuffer) und optional control (Puffer für Ancillary-Data) vorbefüllt werden. Nach dem Aufruf enthält es die empfangenen Daten, die tatsächliche Absenderadresse und alle Steuernachrichten.
Die Funktion ist Teil der Socket-Erweiterung und steht nur auf Plattformen zur Verfügung, die recvmsg(2) unterstützen (Linux, macOS, BSD). Unter Windows ist sie nicht verfügbar.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $socket Pflicht | Socket | Ein gültiges Socket-Objekt, das zuvor mit socket_create() erzeugt und mit einem lokalen Endpunkt verbunden wurde. |
|
| $message Pflicht | array | Wird per Referenz übergeben. Muss vor dem Aufruf initialisiert sein, z. B. mit ['name' => [], 'iov' => [''], 'control' => '']. Nach dem Aufruf enthält es die Schlüssel name (Absenderadresse), iov (Empfangspuffer-Array), control (Steuernachrichten) und flags (Nachrichten-Flags). |
|
| $flags | int | 0 | Bitmaske aus Empfangs-Flags, z. B. MSG_WAITALL, MSG_PEEK oder MSG_DONTWAIT. Wird als zweites Argument an recvmsg(2) weitergegeben. |
Rückgabewert
int zurück. Bei einem Fehler wird false zurückgegeben; der Fehlercode kann mit socket_last_error() abgefragt werden.Beispiele
Einfacher UDP-Empfang mit socket_recvmsg()
<?php
// Server-Seite: UDP-Socket erstellen und binden
$server = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($server, '127.0.0.1', 9000);
// Nachrichtenstruktur vorbereiten
$message = [
'name' => [], // Absenderadresse wird hier eingetragen
'iov' => [str_repeat('\0', 1024)], // Empfangspuffer (1 KB)
'control' => '', // Ancillary-Data-Puffer (hier leer)
];
echo "Warte auf UDP-Paket...\n";
$bytes = socket_recvmsg($server, $message, 0);
if ($bytes === false) {
echo 'Fehler: ' . socket_strerror(socket_last_error($server)) . "\n";
} else {
$absender = $message['name'];
$daten = $message['iov'][0];
echo "Empfangen ($bytes Byte) von {$absender['addr']}:{$absender['port']}\n";
echo 'Inhalt: ' . substr($daten, 0, $bytes) . "\n";
}
socket_close($server);
File-Descriptor-Passing über Unix-Domain-Socket
<?php
// Empfänger-Seite: Unix-Domain-Socket, der einen Dateideskriptor entgegennimmt
$sock = socket_create(AF_UNIX, SOCK_STREAM, 0);
@unlink('/tmp/fd_pass.sock');
socket_bind($sock, '/tmp/fd_pass.sock');
socket_listen($sock);
$client = socket_accept($sock);
$message = [
'name' => [],
'iov' => [str_repeat('\0', 256)],
// Ausreichend Puffer für SCM_RIGHTS Ancillary-Data reservieren
'control' => str_repeat('\0', 1024),
];
$bytes = socket_recvmsg($client, $message, 0);
if ($bytes !== false) {
echo 'Nutzdaten: ' . substr($message['iov'][0], 0, $bytes) . "\n";
// Steuernachrichten (z. B. übergebene FDs) auswerten
foreach ($message['control'] as $ctrl) {
if ($ctrl['level'] === SOL_SOCKET && $ctrl['type'] === SCM_RIGHTS) {
echo 'Empfangene Dateideskriptoren: ';
echo implode(', ', $ctrl['data']) . "\n";
}
}
}
socket_close($client);
socket_close($sock);
unlink('/tmp/fd_pass.sock');
// Wichtig · Fallstricke
Plattformverfügbarkeit: socket_recvmsg() ist nur auf POSIX-Systemen (Linux, macOS, BSD) verfügbar. Unter Windows existiert die Funktion nicht, da recvmsg(2) dort nicht implementiert ist.
Puffergröße: Der iov-Eintrag im $message-Array muss mit einem ausreichend großen String vorinitialisiert werden (str_repeat('\0', N)). Ist der Puffer zu klein, werden empfangene Daten stillschweigend abgeschnitten und das Flag MSG_TRUNC gesetzt.
Sicherheit bei Ancillary-Data: Beim Empfang von Dateideskriptoren via SCM_RIGHTS müssen die empfangenen FDs nach Verwendung explizit mit fclose() bzw. den entsprechenden Socket-Funktionen geschlossen werden, da sie sonst als Dateileck bestehen bleiben.
Fehlerbehandlung: Im Fehlerfall gibt die Funktion false zurück. Der genaue Fehler sollte immer mit socket_last_error($socket) und socket_strerror() ausgelesen werden, da typische Fehler wie EAGAIN (kein Daten vorhanden bei nicht-blockierendem Socket) von echten Fehlern unterschieden werden müssen.