Socket create listen: примеры (PHP)
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Последовательное использование этих функций дает больший контроль над параметрами сокета. Позволяет указать домен (AF_INET, AF_INET6, AF_UNIX) и тип сокета (SOCK_STREAM, SOCK_DGRAM).
Более высокоуровневая функция для создания серверных сокетов. Работает с потоковыми контекстами и поддерживает 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()
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Тип возвращаемого значения изменен с resource на Socket (объект). Функция теперь возвращает объект Socket или false при ошибке.
Было введено исключение Error при невозможности создать сокет, хотя функция по-прежнему возвращала false.
Для кода, совместимого с PHP 8, необходимо проверять возвращаемое значение на false и использовать объектный синтаксис при работе с сокетами.
// Создание основного слушающего сокета
$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);
$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);
}