WebSocket 在 PHP 中的应用:创建高级实时应用程序

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

WebSocket 在 PHP 中的应用:从理论到生产级解决方案

\n\n

WebSocket 协议彻底改变了 Web 开发,使得创建基于单个 TCP 连接的全功能实时应用程序成为可能。与经典的 HTTP(客户端不断发起请求)不同,WebSocket 建立了一个双向通信通道,服务器可以随时发送数据。这对于聊天、交易平台、在线游戏和监控系统至关重要。

\n\n

许多开发人员错误地认为 PHP 由于其同步特性而不适合实时任务。然而,像 Ratchet 和 ReactPHP 这样的现代工具完全改变了这一看法。在本文中,我们将探讨使用 PHP 创建可扩展 WebSocket 应用程序的高级技术。

\n\n

PHP 中 WebSocket 服务器的架构

\n\n

选择正确的技术栈

\n\n

对于生产级解决方案,通过 socket_create 运行的简单库并不适用。需要事件驱动的方法。推荐的技术栈:

\n\n
    \n
  • ReactPHP — 用于异步输入/输出的事件循环
  • \n
  • Ratchet — 基于 ReactPHP 的 WebSocket 组件
  • \n
  • Redis — 用于进程间通信的发布/订阅
  • \n
  • Supervisor — 用于确保正常运行时间的进程管理器
  • \n
\n\n

使用 Ratchet 的基础服务器

\n\n

让我们考虑创建一个能够处理数千个连接的全功能 WebSocket 服务器:

\n\n
use Ratchet\\MessageComponentInterface;\nuse Ratchet\\ConnectionInterface;\nuse React\\EventLoop\\Factory;\nuse React\\Socket\\Server;\nuse Ratchet\\Server\\IoServer;\nuse Ratchet\\Http\\HttpServer;\nuse Ratchet\\WebSocket\\WsServer;\n\nclass ChatServer implements MessageComponentInterface {\n    protected $clients;\n    protected $redis;\n\n    public function __construct() {\n        $this->clients = new \\SplObjectStorage;\n        $this->redis = new \\Predis\\Client([\n            'scheme' => 'tcp',\n            'host'   => '127.0.0.1',\n            'port'   => 6379,\n        ]);\n        // 订阅 Redis 频道以实现跨服务器同步\n        $this->redis->subscribe(['chat_messages'], function($redis, $channel, $message) {\n            $this->broadcast(json_decode($message, true));\n        });\n    }\n\n    public function onOpen(ConnectionInterface $conn) {\n        $this->clients->attach($conn);\n        echo "新连接: {$conn->resourceId}\\n";\n    }\n\n    public function onMessage(ConnectionInterface $from, $msg) {\n        $data = json_decode($msg, true);\n        \n        // 消息验证\n        if ($this->validateMessage($data)) {\n            // 发布到 Redis 以供其他服务器使用\n            $this->redis->publish('chat_messages', json_encode($data));\n            // 发送给本地客户端\n            $this->broadcast($data, $from);\n        }\n    }\n\n    public function onClose(ConnectionInterface $conn) {\n        $this->clients->detach($conn);\n        echo "连接已关闭: {$conn->resourceId}\\n";\n    }\n\n    public function onError(ConnectionInterface $conn, \\Exception $e) {\n        echo "错误: {$e->getMessage()}\\n";\n        $conn->close();\n    }\n\n    protected function broadcast(array $data, ?ConnectionInterface $exclude = null) {\n        foreach ($this->clients as $client) {\n            if ($exclude === null || $client !== $exclude) {\n                $client->send(json_encode($data));\n            }\n        }\n    }\n\n    protected function validateMessage(array $data): bool {\n        return isset($data['type'], $data['payload']) && \n               in_array($data['type'], ['message', 'typing', 'status']);\n    }\n}\n\n// 启动服务器\n$loop = Factory::create();\n$webSock = new Server('0.0.0.0:8080', $loop);\n$webServer = n                

博客

书籍推荐