什么是 WebSocket,为什么在 PHP 中需要它
传统的 HTTP 协议遵循“请求-响应”模式:客户端发送请求,服务器处理并返回响应。为了获取新数据,客户端必须不断刷新页面或使用 AJAX 轮询(定期向服务器发送请求)。这种方法会造成不必要的负载,并且无法提供真正的“实时”连接。
WebSocket(RFC 6455)是一种协议,它在客户端(浏览器)和服务器之间建立持久的双向连接。在握手之后,数据可以实时双向传输,无需重复的 HTTP 请求。它是以下场景的理想解决方案:
- 聊天和即时通讯
- 新闻推送和通知
- 协同文档编辑
- 游戏和拍卖
- 监控和仪表盘
许多人认为 PHP 由于其同步特性而不适合实时任务。然而,随着 Ratchet 和 ReactPHP 等库的出现,情况发生了根本性变化。PHP 可以通过使用事件驱动架构和非阻塞 I/O 来高效地处理 WebSocket。
PHP 中 WebSocket 应用的架构
在编写代码之前,了解 PHP 服务器端 WebSocket 连接的工作原理非常重要。
连接建立步骤
- HTTP 握手: 客户端发送一个带有
Upgrade: websocket头部的特殊 HTTP 请求。服务器验证Sec-WebSocket-Key密钥,并返回状态码为 101 Switching Protocols 的响应。 - 协议切换: 握手成功后,连接切换到 WebSocket 模式。后续的数据交换通过二进制帧进行。
- 全双工通信: 在连接被任一方关闭之前,服务器和客户端可以随时发送消息。
同步 PHP 与异步 PHP
普通的 PHP 脚本是同步运行的:一个请求对应一个进程,响应后脚本结束。WebSocket 需要一个持续运行的进程来监听端口并处理多个并发连接。这时 ReactPHP 就派上了用场——它是一个为 PHP 实现事件循环的库。
Ratchet 库构建在 ReactPHP 之上,并提供了一个方便的接口来创建 WebSocket 服务器。它负责处理底层的套接字操作、帧解析和连接管理。
实践实现:构建实时聊天
让我们使用 Ratchet 创建一个简单的 WebSocket 聊天。这个示例可以适用于任何实时任务。
步骤 1:安装依赖
确保你已经安装了 Composer(PHP 的依赖管理器)。安装 Ratchet 及其依赖:
composer require cboden/ratchet步骤 2:创建处理器类
创建一个名为 ChatServer.php 的文件,用于管理连接和消息:
<?phpnamespace MyApp;
use Ratchet\\MessageComponentInterface;use Ratchet\\ConnectionInterface;
class ChatServer implements MessageComponentInterface{ protected $clients;
public function __construct() { // SplObjectStorage — 一种方便存储连接对象的方式 $this->clients = new \\SplObjectStorage; echo "服务器已启动!"; }
public function onOpen(ConnectionInterface $conn) { // 新客户端已连接 $this->clients->attach($conn); echo "新连接:{$conn->resourceId}"; }
public function onMessage(Connectio