PHP RFC6455 WebSocket 纯协议实现:Ratchet + Workerman 优雅解耦方案
标签: PHP / WebSocket / RFC6455 / Workerman / Ratchet / 实时通信 / 开源 / PSR-7 / 网络协议
原文: 微信公众号「开源技术小栈」https://mp.weixin.qq.com/s/SL9ej1gVGWMuT877vh7oxQ
纯手写 WebSocket 协议?容易踩坑
WebSocket 协议(RFC 6455)规范了从 HTTP/1.1 升级握手、消息分帧(文本/二进制、掩码、控制帧)、连接状态管理、安全性等核心机制。
但纯手写协议处理非常容易出错——半包、碎片、掩码、超时,每一个都是坑。
Ratchet RFC6455 正是 PHP 生态中最成熟的 I/O 无关协议处理器。它只负责协议逻辑,不处理网络 I/O。结合 Workerman(高性能异步 PHP 框架),可以轻松实现稳定、可扩展的 WebSocket 服务。
核心设计:协议层与传输层完全解耦
Ratchet RFC6455 是一个针对 RFC6455 规范的协议处理工具,包含:
- 服务器端和客户端握手组件
- 消息传递协议协商
- PSR-7 接口处理 HTTP 升级协商
核心优势:独立的、不依赖特定框架、不处理任何输入/输出操作。
┌──────────────────────────┐
│ Ratchet RFC6455 │ ← 协议层(握手/分帧/掩码/分片)
├──────────────────────────┤
│ Workerman │ ← 传输层(TCP 连接管理)
├──────────────────────────┤
│ 业务逻辑 │ ← 你写的代码
└──────────────────────────┘
环境准备
安装依赖
composer require workerman/workerman ratchet/rfc6455 guzzlehttp/psr7
RFC 6455 规范核心
| 机制 | 说明 |
|---|---|
| 握手(Handshake) | 从 HTTP/1.1 升级为 WebSocket |
| 帧(Frame) | 消息分帧(文本/二进制、掩码、控制帧:Ping/Pong/Close) |
| 状态管理 | 连接、消息队列、分片、关闭 |
| 安全性 | 掩码(masking)、扩展(permessage-deflate)、子协议(Sec-WebSocket-Protocol) |
完整实现代码
自定义协议类 WebSocketRFC6455
关键设计点:
- input() 方法:判断是否完成 HTTP 握手头(检测
\r\n\r\n),握手后全部消费 - decode() 方法:握手阶段调用 handleHandshake(),握手后交给 MessageBuffer 解析
- encode() 方法:使用 Ratchet Frame 类封装 WebSocket 文本帧
- handleHandshake() 方法:用 ServerNegotiator 完成握手,创建 MessageBuffer 处理后续消息
Worker 配置
$worker = new Worker('tcp://0.0.0.0:8486');
$worker->count = 4;
$worker->protocol = WebSocketRFC6455::class;
$worker->onMessage = function (TcpConnection $connection, $data) {
echo "收到消息: [$data]\n";
$connection->send("服务器回复: 收到你的消息 - $data");
};
$worker->onClose = function (TcpConnection $connection) {
echo "连接关闭: {$connection->getRemoteIp()}\n";
};
Worker::runAll();
运行与测试
Step 1:启动服务器
php start.php start
Step 2:浏览器测试
var ws = new WebSocket('ws://127.0.0.1:8486');
ws.onmessage = function(event) {
console.log('收到消息: ' + event.data);
};
ws.send("Hello WebSocket!");
Step 3:调试输出
-------------------------------------------- WORKERMAN --------------------------------------------
Workerman/5.2.2 PHP/8.4.15 (JIT off) Linux/6.18.33.1-microsoft-standard-WSL2
--------------------------------------------- WORKERS ---------------------------------------------
event-loop proto user worker listen count state
select tcp root none tcp://0.0.0.0:8486 4 [OK]
---------------------------------------------------------------------------------------------------
Press Ctrl+C to stop. Start success.
WebSocket 握手成功: 172.18.0.1
收到消息: [Hello WebSocket!]
核心设计解析
握手阶段
| 步骤 | 说明 |
|---|---|
| 1. input() | 返回 \r\n\r\n 之前的长度,等待完整 HTTP 头 |
| 2. decode() | 调用 handleHandshake(),使用 ServerNegotiator 完成 101 响应 |
| 3. MessageBuffer | 握手成功后创建,准备接收后续 WebSocket 帧 |
消息处理阶段
| 步骤 | 说明 |
|---|---|
| 1. input() | 全部消费,MessageBuffer 内部处理分帧与缓冲 |
| 2. decode() | 调用 $connection->messageBuffer->onData($buffer),内部处理分片、掩码、Ping/Pong |
| 3. onMessage | 回调自动触发,队列中取出 getPayload() |
| 4. encode() | 使用 Ratchet Frame 类封装为 WebSocket 帧 |
架构对比:自定义协议 vs 内置协议
| 对比项 | 自定义协议(本文) | Workerman 内置 websocket:// |
|---|---|---|
| 代码量 | ~120 行 | ~30 行 |
| 协议控制 | 完全自定义,可深度定制 | 使用内置实现 |
| 适用场景 | 需要自定义握手/分帧/扩展 | 聊天室、实时仪表盘等常见场景 |
| 学习价值 | 深入理解 RFC6455 协议 | 快速上手 |
| 扩展性 | 高,可自行添加子协议协商 | 中,依赖 Workerman 版本更新 |
技术要点总结
为什么要用 Ratchet RFC6455?
- 纯协议处理——不绑定 I/O,可搭配任何传输层
- PSR-7 兼容——HTTP 升级协商标准化
- 完整分帧处理——自动处理半包、碎片、掩码
- 生产级成熟——Ratchet 是 PHP WebSocket 生态标杆
核心组件
| 组件 | 作用 |
|---|---|
| ServerNegotiator | WebSocket 握手协商 |
| RequestVerifier | 验证握手请求合法性 |
| MessageBuffer | 消息缓冲与分帧处理 |
| Frame | WebSocket 帧封装 |
| CloseFrameChecker | 关闭帧检测 |
总结
Ratchet RFC6455 + Workerman 是 PHP 中最优雅的 WebSocket 协议实现方式。它把协议层(RFC6455)与传输层(Workerman)完全解耦,让你专注于业务逻辑。
选型建议:
- 🎯 如果只是想快速搭建聊天室/实时仪表盘,直接用 Workerman 内置
websocket://协议(30 行代码)——更简单、更稳定 - 🔬 如果需要深度定制 WebSocket 协议(自定义握手、子协议、扩展),使用本文的 Ratchet RFC6455 自定义协议方案
Keywords: PHP WebSocket, RFC6455, Workerman, Ratchet, 实时通信, 协议解析, PSR-7, MessageBuffer, TCP Socket, 开源