WebSocket библиотека Ratchet для PHP: создание реального времени на сайте

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Что такое WebSocket и зачем нужна библиотека Ratchet для PHP?

WebSocket — это протокол, обеспечивающий постоянное двустороннее соединение между клиентом (браузером) и сервером. В отличие от классического HTTP, где запросы инициирует только клиент, WebSocket позволяет серверу отправлять данные мгновенно, без ожидания запроса. Это идеальное решение для чатов, уведомлений в реальном времени, онлайн-игр, трекеров и любых приложений, где важна низкая задержка.

Стандартный PHP не имеет встроенной поддержки WebSocket, но библиотека Ratchet (использующая компонент ReactPHP) заполняет этот пробел. Ratchet — это асинхронная библиотека, которая позволяет запускать WebSocket-сервер прямо из PHP, обрабатывая множество соединений одновременно без блокировки.

Основные возможности Ratchet

  • Асинхронность — на основе ReactPHP, не блокирует поток при ожидании данных.
  • Поддержка протоколов — WebSocket (RFC 6455), а также HTTP-компоненты (для гибридных приложений).
  • Простота — минимальный код для запуска сервера.
  • Масштабирование — можно комбинировать с ZeroMQ или Redis для работы в кластере.
  • Совместимость — работает с любыми современными браузерами через встроенный объект WebSocket.

Установка Ratchet

Установка выполняется через Composer. Откройте терминал в корне проекта и выполните:

composer require cboden/ratchet

После установки в папке vendor появятся все зависимости, включая ReactPHP.

Создание простого WebSocket-сервера на Ratchet

Создадим файл server.php:

<?php
require 'vendor/autoload.php';

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;

class Chat implements MessageComponentInterface {
    protected $clients;

    public function __construct() {
        $this->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();

Пояснение кода

  • Chat — класс, реализующий MessageComponentInterface. В onOpen мы сохраняем соединение, в onMessage — рассылаем сообщение всем, кроме отправителя.
  • IoServer::factory — создаёт сервер на основе ReactPHP. Мы оборачиваем наш компонент в WsServer (для WebSocket) и HttpServer (для совместимости с HTTP-запросами).
  • Сервер слушает порт 8080. Запустите его командой: php server.php.

Клиентская часть (JavaScript)

Создайте HTML-файл client.html:

<!DOCTYPE html>
<html>
<head>
    <title>WebSocket чат</title>
    <script>
        const ws = new WebSocket('ws://localhost:8080');

        ws.onopen = function() {
            console.log('Соединение установлено');
            document.getElementById('status').innerText = 'Подключено';
        };

        ws.onmessage = function(event) {
            const msgDiv = document.createElement('div');
            msgDiv.innerText = event.data;
            document.getElementById('messages').appendChild(msgDiv);
        };

        ws.onclose = function() {
            console.log('Соединение закрыто');
            document.getElementById('status').innerText = 'Отключено';
        };

        function sendMessage() {
            const input = document.getElementById('msg');
            ws.send(input.value);
            input.value = '';
        }
    </script>
</head>
<body>
    <h3>WebSocket чат</h3>
    &                    

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