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

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

Базовый пример TCP-сервера
<?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
Использование с флагом backlog
<?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

Функция stream_socket_server создает и сразу переводит сокет в режим прослушивания. Она работает на более высоком уровне абстракции, поддерживая SSL и асинхронные операции через stream_select.

fsockopen и pfsockopen

Функции fsockopen и pfsockopen предназначены для клиентских соединений, но могут использоваться для простых серверных задач. pfsockopen создает постоянное соединение.

Рекомендации по выбору

socket_listen используется для низкоуровневого контроля над сокетами. stream_socket_server предпочтительнее для большинства задач из-за простоты интеграции с потоками и поддержки шифрования.

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

Python: socket.listen
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 8080))
s.listen(5)
print('Сервер запущен')
Сервер запущен
JavaScript (Node.js): server.listen
const net = require('net');
const server = net.createServer();
server.listen(8080, '127.0.0.1', () => {
    console.log('Сервер слушает порт 8080');
});
Сервер слушает порт 8080
C: listen()
#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
Некорректный backlog
<?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

PHP 8.4

Добавлен необязательный параметр $flags. Поддерживается флаг SOCKET_LISTEN_BACKGROUND, позволяющий функции выполняться в фоновом режиме, не блокируя основной поток.

Предыдущие версии

В PHP 8.0 и 7.x функция не претерпевала значительных изменений. Поведение и сигнатура оставались стабильными.

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

Мультипротокольный сервер
Пример php
<?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
<?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
}
?>

Сервер продолжает работу, даже если нет подключений.

Использование с socket_select
Пример php
<?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);
            }
        }
    }
}
?>

Пример демонстрирует обработку нескольких подключений.

PHP socket_listen function comments

En
Socket listen Listens for a connection on a socket