Socket set block: примеры (PHP)

Использование socket_set_block для управления режимом сокета
Раздел: Сокеты
socket_set_block(resource socket): bool

Описание функции socket_set_block

Назначение функции

Функция socket_set_block переводит сокет в блокирующий режим. В этом режиме операции чтения или записи будут ожидать доступа к ресурсу, пока он не станет доступен. Это поведение противоположно неблокирующему режиму, установленному функцией socket_set_nonblock.

Аргументы функции

Функция принимает один обязательный параметр:

  • socket - ресурс сокета, созданный функцией socket_create или socket_accept.

Возвращает true в случае успеха и false при возникновении ошибки.

Базовые примеры использования

Пример установки блокирующего режима
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
    echo "Ошибка создания сокета: " . socket_strerror(socket_last_error());
} else {
    // Установка блокирующего режима
    if (socket_set_block($socket)) {
        echo "Сокет переведен в блокирующий режим.\n";
    } else {
        echo "Ошибка установки режима: " . socket_strerror(socket_last_error($socket));
    }
    socket_close($socket);
}
?>
Сокет переведен в блокирующий режим.
Пример с обработкой ошибки
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_close($socket);
// Попытка установить режим на закрытом сокете
if (!socket_set_block($socket)) {
    echo "Ошибка: " . socket_strerror(socket_last_error($socket));
}
?>
Ошибка: Заданный ресурс не является корректным ресурсом сокета

Альтернативные функции в PHP

socket_set_nonblock

Функция переводит сокет в неблокирующий режим, где операции завершаются немедленно. Используется при необходимости асинхронной обработки соединений.

stream_set_blocking

Применяется для потоковых ресурсов, таких как файлы или сетевые соединения, открытые через функции вроде fsockopen. Более универсальна для работы с потоками.

Выбор функции

socket_set_block предпочтительна при низкоуровневой работе с сокетами, созданными через расширение Socket. Для потоков, открытых через стандартные функции ввода-вывода, используют stream_set_blocking.

Аналоги в других языках

Python: setblocking
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(True)  # Аргумент 1 или True
print("Режим блокировки установлен")
Режим блокировки установлен
JavaScript (Node.js): socket.setTimeout

В Node.js нет прямой аналогии, но блокировка достигается через установку таймаута или использование синхронных методов.

const net = require('net');
const socket = new net.Socket();
socket.setTimeout(0); // Установка бесконечного таймаута
console.log("Сокет настроен на блокирующее поведение");
Сокет настроен на блокирующее поведение
Отличия от PHP

В Python метод setblocking принимает булевый аргумент, а в PHP функция socket_set_block не имеет параметров для степени блокировки. В Node.js управление режимом более комплексное и часто связано с событийным циклом.

Типичные ошибки

Передача некорректного ресурса
<?php
$invalidResource = fopen('php://temp', 'r');
if (!socket_set_block($invalidResource)) {
    echo "Код ошибки: " . socket_last_error($invalidResource) . "\n";
    echo "Текст ошибки: " . socket_strerror(socket_last_error($invalidResource));
}
?>
Код ошибки: 9
Текст ошибки: Заданный ресурс не является корректным ресурсом сокета
Использование после закрытия сокета
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_close($socket);
if (!socket_set_block($socket)) {
    echo "Ошибка после закрытия: " . socket_strerror(socket_last_error($socket));
}
?>
Ошибка после закрытия: Заданный ресурс не является корректным ресурсом сокета
Отсутствие проверки возвращаемого значения
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_block($socket); // Потенциальная ошибка игнорируется
socket_connect($socket, '192.0.2.0', 80); // Может зависнуть в блокирующем режиме
?>

Результат зависит от сетевых условий: соединение может зависнуть при недоступном адресе.

Изменения в версиях PHP

Функция socket_set_block остается стабильной в PHP 8. Основные изменения связаны с улучшением обработки ошибок и строгостью типов. В PHP 8.0 улучшены сообщения об ошибках при передаче неверных аргументов. Ранее в PHP 5.x и 7.x не было значительных изменений в поведении функции.

Расширенные примеры

Переключение между режимами
Пример php
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '127.0.0.1', 8080);
socket_listen($socket);

// Установка неблокирующего режима для accept
socket_set_nonblock($socket);
$client = @socket_accept($socket); // Не блокируется
if ($client === false) {
    echo "Нет ожидающих соединений.\n";
}

// Возврат в блокирующий режим
socket_set_block($socket);
echo "Ожидание соединения...\n";
$client = socket_accept($socket); // Блокируется до подключения
echo "Клиент подключен.\n";
socket_close($client);
socket_close($socket);
?>
Нет ожидающих соединений.
Ожидание соединения...
Клиент подключен.
Работа в многопоточном окружении
Пример php
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_block($socket);
socket_connect($socket, 'example.com', 80);

// Блокирующая запись
$data = "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n";
$written = socket_write($socket, $data, strlen($data));
if ($written !== false) {
    echo "Записано байт: $written\n";
    // Блокирующее чтение
    $response = socket_read($socket, 2048);
    echo "Получено данных: " . strlen($response) . " байт\n";
} else {
    echo "Ошибка записи: " . socket_strerror(socket_last_error($socket));
}
socket_close($socket);
?>
Записано байт: 57
Получено данных: 2048 байт
Интеграция с socket_select
Пример php
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_block($socket);
socket_connect($socket, 'example.com', 80);

$read = [$socket];
$write = [$socket];
$except = null;

// Ожидание возможности запиши (в блокирующем режиме может не требоваться)
$changed = socket_select($read, $write, $except, 5);
if ($changed > 0) {
    if (in_array($socket, $write)) {
        echo "Сокет готов для записи.\n";
    }
}
socket_close($socket);
?>
Сокет готов для записи.

PHP socket_set_block function comments

En
Socket set block Sets blocking mode on a socket resource