Когда я впервые услышал про вебсокеты, подумал: «Очередная модная штука». Но потом понял — это реально меняет правила игры. Обычный сайт работает так: ты кликнул — сервер ответил. А с вебсокетами сервер сам может отправить данные в любой момент. Это как радио: ты включаешь, и музыка играет, а не каждый раз жмёшь кнопку. В этой статье разберём, как подключить вебсокеты к PHP, чтобы сделать чат, уведомления или онлайн-игру. Будет просто и с примерами.

Digital-студия WNDER

Ссылка на оригинальную статью

Что такое вебсокеты и зачем они нужны

Представь, что ты заказываешь пиццу. Обычный сайт — это как звонить в пиццерию каждую минуту: «Ну что, готово?» А вебсокет — это когда тебе сам курьер звонит: «Готово, несу!» В техническом смысле вебсокет — это постоянное соединение между браузером и сервером. Через него можно передавать данные в обе стороны без перезагрузки страницы.

Зачем это нужно? Вот примеры:

  • Онлайн-чаты и поддержка — сообщения приходят мгновенно.
  • Биржевые котировки — цены обновляются сами.
  • Многопользовательские игры — ходы передаются в реальном времени.
  • Уведомления о новых заказах в админке.

Раньше для этого использовали «долгие опросы» (long polling) — это когда браузер постоянно спрашивает сервер: «Есть что-то новое?» Но это расточительно. Вебсокеты — как разговор по телефону: линия открыта, и слова летят сразу.

Как работает вебсокет на пальцах

Давай разберём простую аналогию. Обычный HTTP-запрос — это письмо. Ты отправляешь его, получаешь ответ, и всё — связь закончена. Вебсокет — это как открыть туннель между двумя домами. Можно ходить туда-сюда без стука в дверь.

Технически это выглядит так:

  1. Браузер отправляет HTTP-запрос с заголовком Upgrade: websocket.
  2. Сервер соглашается и отвечает 101 Switching Protocols.
  3. Дальше соединение становится постоянным, и обе стороны могут слать сообщения.

В PHP нет встроенной поддержки вебсокетов, как в Node.js. Но это не проблема — есть библиотеки. Самая популярная — Ratchet. Она позволяет поднять вебсокет-сервер на чистом PHP. Есть ещё Workerman, но он требует установки расширения и работает быстрее. Для начала хватит Ratchet.

Настраиваем окружение и ставим библиотеку

Чтобы попробовать вебсокеты, нужен PHP версии 7.4 или выше и Composer — это такой менеджер пакетов для PHP. Если Composer нет, скачай с getcomposer.org.

Создаём папку для проекта и в ней выполняем команду:

composer require cboden/ratchet

Эта команда установит библиотеку и все её зависимости. Теперь создадим файл server.php — это будет наш вебсокет-сервер.

clients = new \SplObjectStorage;
    }

    public function onOpen(ConnectionInterface $conn) {
        $this->clients->attach($conn);
        echo "Новое соединение: {$conn->resourceId}\n";
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        foreach ($this->clients as $client) {
            if ($from !== $client) {
                $client->send($msg);
            }
        }
    }

    public function onClose(ConnectionInterface $conn) {
        $this->clients->detach($conn);
        echo "Соединение закрыто: {$conn->resourceId}\n";
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "Ошибка: {$e->getMessage()}\n";
        $conn->close();
    }
}

$server = IoServer::factory(
    new HttpServer(
        new WsServer(
            new Chat()
        )
    ),
    8080
);

echo "Сервер запущен на порту 8080\n";
$server->run();

Это простейший чат-сервер. Он хранит список всех подключённых клиентов и пересылает сообщения от одного всем остальным. Запустить его можно командой:

php server.php

Теперь сервер слушает порт 8080. Но чтобы браузер мог подключиться, нужна клиентская часть на JavaScript.

Пишем клиентскую часть на JavaScript

В браузере вебсокеты работают через объект WebSocket. Это встроено в современные браузеры, ничего устанавливать не нужно. Создадим файл index.html.




    Чат на вебсокетах


    

Простой чат

    Открой этот файл в браузере (можно просто двойным кликом). Но есть нюанс: если открыть через file://, некоторые браузеры могут блокировать WebSocket. Лучше запустить локальный сервер, например, встроенный в PHP:

    php -S localhost:8000

    И в адресной строке ввести http://localhost:8000/index.html. Теперь открой две вкладки с этим адресом — и можно общаться между ними.

    Как улучшить: отправка сообщений конкретному клиенту

    В примере выше сообщения уходят всем. Но часто нужно отправлять только определённому пользователю. Например, в личном кабинете. Для этого можно хранить идентификаторы клиентов и привязывать их к пользователям.

    Добавим в класс Chat метод для отправки приватного сообщения:

    public function sendPrivate(ConnectionInterface $to, $msg) {
        $to->send($msg);
    }
    

    И в onMessage можно проверять, если сообщение начинается с «/pm», то отправлять только адресату. Вот пример:

    public function onMessage(ConnectionInterface $from, $msg) {
        if (strpos($msg, '/pm ') === 0) {
            $parts = explode(' ', $msg, 3);
            $targetId = (int)$parts[1];
            $message = $parts[2];
            foreach ($this->clients as $client) {
                if ($client->resourceId === $targetId) {
                    $client->send("Приватное от {$from->resourceId}: $message");
                    break;
                }
            }
        } else {
            foreach ($this->clients as $client) {
                if ($from !== $client) {
                    $client->send($msg);
                }
            }
        }
    }
    

    Теперь, если отправить сообщение вида «/pm 2 Привет», оно уйдёт только клиенту с идентификатором 2. Узнать свой идентификатор можно, например, отправив серверу команду «/id».

    Правило: всегда закрывайте соединение, когда клиент уходит. Иначе сервер будет копить мёртвые подключения и в итоге упадёт. В Ratchet это автоматически при onClose, но если используете другие библиотеки — следите за этим.

    Безопасность и ограничения

    Вебсокеты — это здорово, но у них есть свои подводные камни. Вот что важно знать:

    Проблема Решение
    Соединение может оборваться Реализовать пинг-понг между клиентом и сервером
    Много одновременных подключений Использовать Workerman или Swoole для производительности
    Передача конфиденциальных данных Использовать wss:// (WebSocket Secure) — это как HTTPS

    Также не забывай про валидацию входных данных. Если сервер принимает сообщения от всех, злоумышленник может отправить что-то вредное. Всегда проверяй, что приходит.

    Лайфхак: для продакшена не запускай вебсокет-сервер на том же порту, что и обычный сайт. Лучше использовать отдельный порт (например, 8080) и проксировать через Nginx, чтобы раздавать статику и WebSocket параллельно.

    Что в итоге

    Вебсокеты открывают перед PHP новые возможности. Теперь твой сайт может быть не просто набором страниц, а живым приложением. Мы разобрали:

    • Что такое вебсокеты и где их применять.
    • Как поднять сервер на Ratchet.
    • Как написать клиент на JavaScript.
    • Как отправлять приватные сообщения.
    • Какие есть подводные камни.

    Попробуй запустить пример — это займёт 10 минут. А дальше можно экспериментировать: добавлять комнаты, идентификацию пользователей, хранить историю сообщений. PHP не такой уж и скучный, если знать, как его разбудить.

    Если нужна помощь с разработкой — загляни в Digital-студию WNDER, там знают толк в веб-технологиях.

    Студия WNDER