Socket recvfrom: примеры (PHP)
socket_recvfrom(resource socket, string &buf, int len, int flags, string &name [, int &port]): intОсновы функции socket_recvfrom
Функция socket_recvfrom применяется для получения данных из сокета, преимущественно при работе с UDP-протоколом. Она позволяет получить не только данные, но и адрес отправителя.
socket_recvfrom(Socket $socket, string &$data, int $length, int $flags, string &$address, int &$port = null): int|false
Созданный ресурс сокета, возвращенный функцией socket_create.
Переменная, куда будут записаны полученные данные.
Максимальное количество байт для чтения.
Битовое значение флагов: MSG_OOB, MSG_PEEK, MSG_WAITALL, MSG_DONTWAIT.
Переменная для IP-адреса отправителя.
Переменная для порта отправителя.
Базовые примеры использования
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($socket, '127.0.0.1', 9999);
$data = '';
$from = '';
$port = 0;
$received = socket_recvfrom($socket, $data, 1024, 0, $from, $port);
echo "Получено $received байт от $from:$port\n";
echo "Данные: $data\n";Получено 12 байт от 127.0.0.1:54321 Данные: Hello World!
socket_recvfrom($socket, $data, 1024, MSG_PEEK, $from, $port);
echo "Данные остаются в буфере: $data";Данные остаются в буфере: Test message
Похожие функции в PHP
Читает данные из подключенного сокета, но не возвращает адрес отправителя. Используется для TCP-соединений.
Работает с потоковыми сокетами, возвращает данные без изменения буфера. Удобна для работы с файловыми дескрипторами.
Читает данные из сокета с заданной длиной, но без поддержки флагов и адреса отправителя.
Аналоги в других языках
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('127.0.0.1', 9999))
data, addr = sock.recvfrom(1024)
print(f"Получено от {addr}: {data.decode()}")const dgram = require('dgram');
const server = dgram.createSocket('udp4');
server.on('message', (msg, rinfo) => {
console.log(`Получено от ${rinfo.address}:${rinfo.port} - ${msg}`);
});
server.bind(9999);Низкоуровневая функция с аналогичной семантикой, требует ручного управления памятью.
Распространенные ошибки
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
$result = socket_recvfrom($socket, $data, 1024, 0, $from, $port);
// Переменные $from и $port передаются по ссылке, но не инициализированыПредупреждение: socket_recvfrom(): 4-й аргумент должен быть корректной переменной
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
// Для TCP сокетов socket_recvfrom не подходит
socket_recvfrom($socket, $data, 1024, 0, $from, $port);Возвращает false, устанавливается код ошибки SOCKET_EOPNOTSUPP
Изменения в версиях PHP
Изменена сигнатура функции: параметры $address и $port теперь передаются по ссылке (добавлен амперсанд &). Ранее они передавались по значению.
Добавлена поддержка флага MSG_DONTWAIT для неблокирующих операций.
Расширенные примеры
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_set_nonblock($socket);
socket_bind($socket, '0.0.0.0', 8888);
$clients = [];
while (true) {
$data = '';
$from = '';
$port = 0;
$len = @socket_recvfrom($socket, $data, 65535, 0, $from, $port);
if ($len !== false) {
$key = $from . ':' . $port;
$clients[$key] = time();
echo "[$key] $data\n";
// Ответ клиенту
socket_sendto($socket, "OK\n", 3, 0, $from, $port);
}
usleep(100000);
}$received = socket_recvfrom($socket, $binary, 4, 0, $from, $port);
$unpacked = unpack('Nint', $binary);
echo "Получено 32-битное число: " . $unpacked['int'];// Ждет получения точного количества байт
$len = socket_recvfrom($socket, $data, 512, MSG_WAITALL, $from, $port);
if ($len === 512) {
echo "Получен полный пакет";
}