Socket set block: примеры (PHP)
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
Функция переводит сокет в неблокирующий режим, где операции завершаются немедленно. Используется при необходимости асинхронной обработки соединений.
Применяется для потоковых ресурсов, таких как файлы или сетевые соединения, открытые через функции вроде fsockopen. Более универсальна для работы с потоками.
socket_set_block предпочтительна при низкоуровневой работе с сокетами, созданными через расширение Socket. Для потоков, открытых через стандартные функции ввода-вывода, используют stream_set_blocking.
Аналоги в других языках
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(True) # Аргумент 1 или True
print("Режим блокировки установлен")Режим блокировки установлен
В Node.js нет прямой аналогии, но блокировка достигается через установку таймаута или использование синхронных методов.
const net = require('net');
const socket = new net.Socket();
socket.setTimeout(0); // Установка бесконечного таймаута
console.log("Сокет настроен на блокирующее поведение");Сокет настроен на блокирующее поведение
В 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
$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
$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 байт
<?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);
?>Сокет готов для записи.