Сетевое программирование на PHP: от сокетов до WebSockets
Когда мы говорим о PHP, первое, что приходит на ум — это веб-разработка: обработка форм, генерация HTML, работа с базами данных. Но PHP — это гораздо больше. Вы когда-нибудь задумывались, что ваш PHP-скрипт может стать не просто «ответчиком» на HTTP-запросы, а полноценным сервером, который общается с другими программами напрямую, через сокеты? Это открывает дверь в мир чат-серверов, игровых лобби, систем мониторинга и IoT-устройств.
В этой статье мы снимем розовые очки и разберем сетевое программирование на PHP на реальных примерах. Вы узнаете, что такое сокеты, как заставить PHP слушать порт, как отправлять и принимать данные по TCP и UDP, и даже прикоснетесь к магии WebSockets. Поехали!
Что такое сокет и зачем он PHP?
Сокет (socket) — это программный интерфейс для обмена данными между процессами, которые могут быть запущены как на одной машине, так и на разных компьютерах в сети. Представьте себе телефонную трубку: у вас есть номер (IP-адрес) и порт (добавочный номер). Вы поднимаете трубку (создаете сокет), набираете номер (соединяетесь) и говорите (передаете данные).
В PHP сокеты реализованы через расширение sockets. Обычно оно отключено по умолчанию, но включить его легко. Сетевое программирование на PHP позволяет создавать:
- TCP-серверы и клиенты (например, для чата или обмена данными с другим сервисом).
- UDP-приложения (стриминг, мониторинг, где потеря пакетов не критична).
- WebSocket-серверы (для real-time приложений в браузере).
Главное преимущество — вы остаетесь в знакомой среде PHP, не переключаясь на C, Java или Node.js. Конечно, для высоконагруженных систем PHP не идеален (из-за однопоточности), но для прототипов, внутренних инструментов или невысоких нагрузок — самое то.
Создаем TCP-сервер на PHP
Начнем с классики: TCP-сервер, который принимает соединения и отправляет приветствие. Это основа любого php сокет приложения.
Шаг 1. Создание сокета
Функция socket_create() — первый шаг. Она принимает три параметра: семейство протоколов (AF_INET для IPv4), тип сокета (SOCK_STREAM для TCP) и протокол (0 — пусть система выберет).
<?php
// Создаем TCP сокет
$socket = socket_create(AF_INET, SOCK_STREAM, 0);
if ($socket === false) {
echo "Ошибка создания сокета: " . socket_strerror(socket_last_error()) . "\n";
exit;
}
echo "Сокет создан успешно.\n";
?>
Шаг 2. Привязка к адресу и порту
Используем socket_bind(). Укажем IP-адрес (0.0.0.0 — слушаем все интерфейсы) и порт (например, 8080).
<?php
$address = '0.0.0.0';
$port = 8080;
if (socket_bind($socket, $address, $port) === false) {
echo "Ошибка привязки: " . socket_strerror(socket_last_error($socket)) . "\n";
exit;
}
echo "Сокет привязан к $address:$port\n";
?>
Шаг 3. Слушаем входящие соединения
Переводим сокет в режим прослушивания с помощью socket_listen(). Второй параметр — максимальная длина очереди соединений.
<?php
if (socket_listen($socket, 5) === false) {
echo "Ошибка прослушивания: " . socket_strerror(socket_last_error($socket)) . "\n";
exit;
}
echo "Сервер запущен, ждем подключений...\n";
?>
Шаг 4. Принимаем клиента
Блокирующая функция socket_accept(). Она ждет, пока кто-то не подключится, и возвращает новый сокет для общения с этим клиентом.
<?php
while (true) {
$client = socket_accept($socket);
if ($client === false) {
echo "Ошибка принятия соединения: " . socket_strerror(socket_last_error($socket)) . "\n";
break;
}
echo "Новый клиент подключился.\n";
// Отправляем приветствие
$message = "Привет, клиент! Ты подключился к PHP-серверу.\n";
socket_write($client, $message, strlen($message));
// Читаем ответ от клиента
$input = socket_read($client, 1024);
if ($input) {
echo "Клиент сказал: " . trim($input) . "\n";
}
// Закрываем соединение с клиентом
socket_close($client);
}
?>
Запустите этот скрипт в консоли (php server.php), а затем подключитесь к нему через telnet localhost 8080. Вы увидите приветствие. Напишите что-нибудь — сервер прочитает и ответит.
Пишем TCP-клиент на PHP
Теперь создадим клиента, который подключается к нашему серверу. Это классический пример php клиент сервер взаимодействия.
<?php
$host = '127.0.0.1';
$port = 8080;
// Создаем сокет
$client = socket_create(AF_INET, SOCK_STREAM, 0);
if ($client === false) {
echo "Ошибка создания сокета: " . socket_strerror(socket_last_error()) . "\n";
exit;
}
// Подключаемся к серверу
$result = socket_connect($client, $host, $port);
if ($result === false) {
echo "Ошибка подключения: " . socket_strerror(socket_last_error($client)) . "\n";
exit;
}
// Читаем приветствие от сервера
$serverMessage = socket_read($client, 1024);
echo "Сервер: " . $serverMessage;
// Отправляем сообщение
$userInput = "Привет, сервер! Я клиент.\n";
socket_write($client, $userInput, strlen($userInput));
// Закрываем соединение
socket_close($client);
?>
Этот клиент подключается, читает приветствие, отправляет ответ и закрывает соединение. Обратите внимание: сетевое программирование на PHP требует внимательности — всегда проверяйте ошибки с помощью socket_last_error() и socket_strerror().
UDP: быстрый, но ненадежный
UDP (User Datagram Protocol) — протокол без установки соединения. Вы просто шлете пакеты, не зная, дойдут ли они. Это идеально для стриминга, игр или мониторинга, где скорость важнее точности