Socket read: примеры (PHP)
socket_read(resource socket, int length [, int type]): string|falseФункция socket_read осуществляет чтение данных из сокета. Она применяется при работе с низкоуровневыми сетевыми соединениями в клиент-серверных приложениях. Функция позволяет считывать указанное количество байт или данные до определенного разделителя.
- socket (resource) - обязательный. Экземпляр сокета, созданный функцией socket_create или полученный от socket_accept.
- length (int) - обязательный. Максимальное количество байтов для чтения. Для чтения до разделителя указывается PHP_NORMAL_READ.
- mode (int) - необязательный. Тип чтения. Возможные значения: PHP_BINARY_READ (чтение двоичных данных, используется по умолчанию) и PHP_NORMAL_READ (чтение строки до символов \\n или \\r).
Чтение 1024 байт в двоичном режиме:
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, '127.0.0.1', 8080);
$data = socket_read($socket, 1024, PHP_BINARY_READ);
echo $data;Привет, сервер!
Использование PHP_NORMAL_READ для построчного чтения:
$data = socket_read($socket, PHP_NORMAL_READ, PHP_NORMAL_READ);
echo $data;Строка 1\n
Для работы с сокетами доступны альтернативные функции:
- stream_socket_recvfrom - чтение данных из сокета, независимо от того, ориентирован он на соединение или нет. Предоставляет больше контроля над флагами.
- fread - чтение данных из файлового потока, включая сокеты, открытые через stream_socket_client. Удобна при использовании потокового контекста.
Выбор зависит от контекста. socket_read применяется при низкоуровневой работе с расширением sockets. stream_socket_recvfrom подходит для более высокоуровневых операций с потоками.
Socket read в Python
Метод recv объекта сокета:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 8080))
data = s.recv(1024)
print(data.decode())Привет от сервера
Событие 'data' на сокете:
const net = require('net');
const client = net.createConnection({ port: 8080 }, () => {
console.log('Подключено');
});
client.on('data', (data) => {
console.log(data.toString());
});Данные от сервера
Socket read в MySQL
В MySQL сетевое чтение инкапсулировано. Прямого аналога нет, но для сетевого взаимодействия используются хранимые процедуры или функции, работающие через SQL-запросы.
Если соединение закрыто, функция возвращает false:
$data = socket_read($socket, 1024);
if ($data === false) {
$error = socket_last_error($socket);
echo 'Ошибка чтения: ' . socket_strerror($error);
}Ошибка чтения: Connection reset by peer
По умолчанию сокет блокирует выполнение, пока данные не будут получены. Это может привести к зависанию скрипта. Решение - установка таймаута:
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, ['sec' => 5, 'usec' => 0]);
$data = socket_read($socket, 1024);Функция socket_read не претерпела значительных изменений в PHP 8. Сохранилась обратная совместимость с предыдущими версиями. В PHP 8.1 улучшена обработка ошибок, но сигнатура и поведение функции остались прежними.
Реализация чтения данных фиксированными чанками:
function readFromSocket($socket, $length) {
$data = '';
$bytesRead = 0;
while ($bytesRead < $length) {
$chunk = socket_read($socket, min(4096, $length - $bytesRead));
if ($chunk === false || $chunk === '') {
break;
}
$data .= $chunk;
$bytesRead += strlen($chunk);
}
return $data;
}Использование socket_set_nonblock для асинхронного чтения:
socket_set_nonblock($socket);
$data = '';
while (true) {
$chunk = socket_read($socket, 1024);
if ($chunk === false && socket_last_error($socket) === SOCKET_EAGAIN) {
// Нет данных для чтения
break;
}
$data .= $chunk;
}
socket_set_block($socket);Чтение структуры с распаковкой:
$binary = socket_read($socket, 12, PHP_BINARY_READ);
if (strlen($binary) === 12) {
$unpacked = unpack('Nint/Cchar', $binary);
print_r($unpacked);
}Array
(
[int] => 123456
[char] => 65
)