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

Использование socket_create_listen для создания серверных сокетов
Раздел: Сокеты
socket_create_listen(int port [, int backlog]): resource|false

Функция socket_create_listen() предоставляет упрощенный способ создания TCP-сокета, который слушает входящие подключения на указанном порту.

Назначение и принцип работы

Функция используется для быстрого запуска TCP-сервера. Она создает сокет, привязывает его к заданному порту и переводит в режим прослушивания. В отличие от последовательного вызова socket_create(), socket_bind() и socket_listen(), эта функция инкапсулирует всю логику в одной операции.

Синтаксис
socket_create_listen(int $port, int $backlog = 128): Socket|false
Аргументы функции
  • $port - номер порта (0-65535). Если указан 0, система автоматически выбирает свободный порт.
  • $backlog - максимальная длина очереди ожидающих подключений. По умолчанию равен 128.

Функция возвращает объект Socket при успешном выполнении или false в случае ошибки.

Простые примеры использования
Базовый пример создания слушающего сокета
// Создание сокета на порту 8080
$socket = socket_create_listen(8080);

if ($socket === false) {
    echo "Ошибка создания сокета: " . socket_strerror(socket_last_error());
} else {
    echo "Сокет успешно создан и слушает порт 8080";
}

// Закрытие сокета
socket_close($socket);
Сокет успешно создан и слушает порт 8080
Использование автоматического выбора порта
// Система сама выберет свободный порт
$socket = socket_create_listen(0);

if ($socket) {
    // Получение информации о привязке
    socket_getsockname($socket, $address, $port);
    echo "Сокет слушает адрес $address на порту $port";
}

socket_close($socket);
Сокет слушает адрес 0.0.0.0 на порту 49152
Альтернативные функции в PHP
socket_create + socket_bind + socket_listen

Последовательное использование этих функций дает больший контроль над параметрами сокета. Позволяет указать домен (AF_INET, AF_INET6, AF_UNIX) и тип сокета (SOCK_STREAM, SOCK_DGRAM).

stream_socket_server

Более высокоуровневая функция для создания серверных сокетов. Работает с потоковыми контекстами и поддерживает SSL/TLS. Часто используется для HTTP-серверов.

Рекомендации по выбору
  • socket_create_listen - для простых TCP-серверов без специальных требований.
  • socket_create + socket_bind + socket_listen - при необходимости тонкой настройки.
  • stream_socket_server - для работы с потоками или использования SSL.
Аналоги в других языках программирования

Socket create listen в Python

import socket

# Создание TCP-сокета
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Привязка к адресу и порту
server_socket.bind(('localhost', 8080))
# Начало прослушивания
server_socket.listen(128)
print(f"Сервер слушает порт 8080")

# Получение подключения
client_socket, address = server_socket.accept()
JavaScript (Node.js)
const net = require('net');

// Создание сервера
const server = net.createServer((socket) => {
    socket.write('Добро пожаловать');
    socket.pipe(socket);
});

// Запуск прослушивания
server.listen(8080, '127.0.0.1', () => {
    console.log('Сервер запущен на порту 8080');
});
Основные отличия
  • В Python и Node.js API для работы с сокетами более высокоуровневое.
  • PHP функция возвращает ресурс/объект сокета, в то время как в Python это объект socket, а в Node.js - объект Server.
  • Обработка ошибок в разных языках имеет свои особенности.
Типичные ошибки и их решение
Порт уже занят
$socket1 = socket_create_listen(8080);
$socket2 = socket_create_listen(8080); // Ошибка!

if ($socket2 === false) {
    echo "Ошибка: " . socket_strerror(socket_last_error());
}
Ошибка: Address already in use
Недостаточно прав для использования порта
// Попытка занять порт ниже 1024 без прав root
$socket = socket_create_listen(80);

if ($socket === false) {
    echo "Ошибка: " . socket_strerror(socket_last_error());
}
Ошибка: Permission denied
Неверный номер порта
$socket = socket_create_listen(70000); // Недопустимый порт

if ($socket === false) {
    echo "Ошибка: " . socket_strerror(socket_last_error());
}
Ошибка: Invalid argument
Изменения в последних версиях PHP
PHP 8.0

Тип возвращаемого значения изменен с resource на Socket (объект). Функция теперь возвращает объект Socket или false при ошибке.

Ранее в PHP 7.0

Было введено исключение Error при невозможности создать сокет, хотя функция по-прежнему возвращала false.

Рекомендации

Для кода, совместимого с PHP 8, необходимо проверять возвращаемое значение на false и использовать объектный синтаксис при работе с сокетами.

Расширенные примеры использования
Многопоточный TCP-сервер
// Создание основного слушающего сокета
$serverSocket = socket_create_listen(9090);

if (!$serverSocket) {
    die("Не удалось создать сокет");
}

// Установка неблокирующего режима
socket_set_nonblock($serverSocket);

$clients = [];

echo "Сервер запущен на порту 9090\n";

while (true) {
    // Принятие нового подключения
    $clientSocket = socket_accept($serverSocket);
    
    if ($clientSocket !== false) {
        echo "Новое подключение принято\n";
        
        // Отправка приветственного сообщения
        $welcome = "Добро пожаловать на сервер\n";
        socket_write($clientSocket, $welcome, strlen($welcome));
        
        $clients[] = $clientSocket;
    }
    
    // Обработка сообщений от клиентов
    foreach ($clients as $key => $client) {
        $data = socket_read($client, 1024);
        
        if ($data !== false && trim($data) !== '') {
            echo "Получено: $data";
            
            // Эхо-ответ
            socket_write($client, "Эхо: $data");
        } elseif ($data === '') {
            // Клиент отключился
            echo "Клиент отключен\n";
            socket_close($client);
            unset($clients[$key]);
        }
    }
    
    usleep(100000); // Пауза 100мс
}

socket_close($serverSocket);
Сервер с обработкой нескольких соединений через select
$socket = socket_create_listen(9999);

if (!$socket) {
    die("Ошибка создания сокета");
}

socket_set_nonblock($socket);

$clients = [];

while (true) {
    $read = array_merge([$socket], $clients);
    $write = $except = null;
    
    // Использование select для мультиплексирования
    if (socket_select($read, $write, $except, 0) > 0) {
        foreach ($read as $readSocket) {
            if ($readSocket === $socket) {
                // Новое подключение
                $newClient = socket_accept($socket);
                socket_set_nonblock($newClient);
                $clients[] = $newClient;
                
                socket_write($newClient, "Привет! Ваш ID: " . (count($clients) - 1) . "\n");
            } else {
                // Данные от существующего клиента
                $data = socket_read($readSocket, 2048);
                
                if ($data === false || $data === '') {
                    // Удаление отключившегося клиента
                    $key = array_search($readSocket, $clients);
                    if ($key !== false) {
                        socket_close($clients[$key]);
                        unset($clients[$key]);
                    }
                } else {
                    echo "Получены данные: $data";
                }
            }
        }
    }
    
    usleep(10000);
}
Получение информации о сокете
$socket = socket_create_listen(0); // Случайный порт

if ($socket) {
    // Локальный адрес и порт
    socket_getsockname($socket, $localAddress, $localPort);
    echo "Локальный адрес: $localAddress\n";
    echo "Локальный порт: $localPort\n";
    
    // Получение опций сокета
    $reuseAddr = socket_get_option($socket, SOL_SOCKET, SO_REUSEADDR);
    echo "SO_REUSEADDR: " . ($reuseAddr ? 'Включен' : 'Выключен') . "\n";
    
    socket_close($socket);
}

PHP socket_create_listen function comments

En
Socket create listen Opens a socket on port to accept connections