Socket listen: примеры (PHP)
socket_listen(resource socket [, int backlog]): boolОписание функции socket_listen
Функция socket_listen в PHP переводит созданный и привязанный сокет в режим прослушивания входящих соединений. Она используется в сетевом программировании для создания серверной части приложений, например, веб-серверов, чатов или игровых серверов.
Функция принимает три аргумента:
- $socket (обязательный) - ресурс сокета, созданный функцией
socket_createи привязанный к адресу с помощьюsocket_bind. - $backlog (опциональный) - максимальная длина очереди ожидающих соединений. Значение по умолчанию зависит от операционной системы, обычно 0 или SOMAXCONN.
- $flags (опциональный, с версии PHP 8.4) - флаги, изменяющие поведение функции. Например,
SOCKET_LISTEN_BACKGROUNDдля запуска в фоновом режиме.
Функция возвращает true при успешном выполнении или false в случае ошибки.
Примеры использования socket_listen
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '127.0.0.1', 8080);
if (socket_listen($socket, 5)) {
echo 'Сервер слушает порт 8080';
}
?>Сервер слушает порт 8080
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '0.0.0.0', 9000);
if (socket_listen($socket, SOMAXCONN)) {
echo 'Очередь установлена на максимальный размер';
}
?>Очередь установлена на максимальный размер
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!socket_listen($socket)) {
$error = socket_last_error($socket);
echo 'Ошибка: ' . socket_strerror($error);
}
?>Ошибка: Socket operation failed
Похожие функции в PHP
Функция stream_socket_server создает и сразу переводит сокет в режим прослушивания. Она работает на более высоком уровне абстракции, поддерживая SSL и асинхронные операции через stream_select.
Функции fsockopen и pfsockopen предназначены для клиентских соединений, но могут использоваться для простых серверных задач. pfsockopen создает постоянное соединение.
socket_listen используется для низкоуровневого контроля над сокетами. stream_socket_server предпочтительнее для большинства задач из-за простоты интеграции с потоками и поддержки шифрования.
Аналоги в других языках
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 8080))
s.listen(5)
print('Сервер запущен')Сервер запущен
const net = require('net');
const server = net.createServer();
server.listen(8080, '127.0.0.1', () => {
console.log('Сервер слушает порт 8080');
});Сервер слушает порт 8080
#include <sys/socket.h>
int listen(int sockfd, int backlog);Отличие от PHP в ручном управлении памятью и необходимости явного закрытия сокетов.
Типичные ошибки
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!socket_listen($socket)) {
echo socket_strerror(socket_last_error($socket));
}
?>Invalid argument
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '127.0.0.1', 8080);
socket_close($socket);
if (!socket_listen($socket)) {
echo socket_strerror(socket_last_error($socket));
}
?>Resource temporarily unavailable
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '127.0.0.1', 8080);
if (!socket_listen($socket, -1)) {
echo socket_strerror(socket_last_error($socket));
}
?>Invalid argument
Изменения в версиях PHP
Добавлен необязательный параметр $flags. Поддерживается флаг SOCKET_LISTEN_BACKGROUND, позволяющий функции выполняться в фоновом режиме, не блокируя основной поток.
В PHP 8.0 и 7.x функция не претерпевала значительных изменений. Поведение и сигнатура оставались стабильными.
Расширенные примеры
<?php
$tcpSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($tcpSocket, '0.0.0.0', 8080);
socket_listen($tcpSocket);
$udpSocket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($udpSocket, '0.0.0.0', 8081);
// Для UDP socket_listen не требуется
echo 'Сервер запущен на TCP 8080 и UDP 8081';
?>Сервер запущен на TCP 8080 и UDP 8081
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '127.0.0.1', 8080);
socket_set_nonblock($socket);
socket_listen($socket);
while (true) {
$client = socket_accept($socket);
if ($client !== false) {
socket_write($client, 'Добро пожаловать');
socket_close($client);
}
usleep(100000); // 100 ms
}
?>Сервер продолжает работу, даже если нет подключений.
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '127.0.0.1', 8080);
socket_listen($socket);
$read = [$socket];
while (true) {
$changed = $read;
if (socket_select($changed, $write, $except, 0) > 0) {
foreach ($changed as $sock) {
if ($sock === $socket) {
$client = socket_accept($socket);
socket_write($client, 'Привет');
socket_close($client);
}
}
}
}
?>Пример демонстрирует обработку нескольких подключений.