Socket read: примеры (PHP)

Работа с функцией socket_read для чтения данных из сокетов
Раздел: Сокеты
socket_read(resource socket, int length [, int type]): string|false
Описание функции socket_read

Функция 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
Похожие функции в PHP

Для работы с сокетами доступны альтернативные функции:

  • 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())
Привет от сервера
JavaScript (Node.js)

Событие '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);
Изменения в PHP 8

Функция socket_read не претерпела значительных изменений в PHP 8. Сохранилась обратная совместимость с предыдущими версиями. В PHP 8.1 улучшена обработка ошибок, но сигнатура и поведение функции остались прежними.

Расширенные примеры
Чтение больших данных по частям

Реализация чтения данных фиксированными чанками:

Пример php
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 для асинхронного чтения:

Пример php
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);
Обработка бинарных данных

Чтение структуры с распаковкой:

Пример php
$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
)

PHP socket_read function comments

En
Socket read Reads a maximum of length bytes from a socket