php 8.5尚未发布,当前最新稳定版为php 8.3;swoole推荐客户端发ping、服务端回pong实现websocket心跳,配合heartbeat_idle_time与heartbeat_check_interval自动清理僵死连接。

PHP 8.5 尚未发布(截至 2024 年 10 月,最新稳定版是 PHP 8.3),因此不存在官方支持的 PHP 8.5。你可能是指基于 Swoole 或 Workerman 等扩展,在 PHP 8.3+ 环境中实现 WebSocket 心跳检测。下面以主流方案 Swoole 为例,说明如何正确配置和实现 WebSocket 心跳机制。
使用 Swoole 实现 WebSocket 心跳检测
Swoole 原生不自动发送心跳帧,需手动在服务端定时向客户端推送 ping,或由客户端主动发 ping/ping 后服务端响应 pong。推荐采用「客户端发 ping、服务端回 pong」方式,更轻量且兼容标准协议。
- WebSocket 协议规定:收到
ping帧必须立即返回pong帧(无需业务逻辑) - Swoole
onMessage回调中可拦截opcode === WEBSOCKET_OPCODE_PING,并调用$fd->push()发送pong - 服务端可通过
tick定时器检查连接是否超时(如 30 秒未收消息),主动 close 不活跃连接
关键代码示例(Swoole 5.0+ + PHP 8.3)
以下为精简可用的心跳处理片段:
$server = new Swoole\WebSocket\Server('0.0.0.0', 9501);
$server->set([
'heartbeat_idle_time' => 60, // 连接空闲超时(秒)
'heartbeat_check_interval' => 25, // 检查间隔(秒),Swoole 自动踢掉无响应连接
]);
$server->on('open', function ($server, $request) {
echo "Client {$request->fd} connected\n";
});
$server->on('message', function ($server, $frame) {
// 自动处理 ping/pong(Swoole 4.8+ 默认已支持,无需手动写)
// 若需自定义逻辑(如记录时间),可在此判断:
if ($frame->opcode === \Swoole\WebSocket\Frame::OPCODE_PING) {
$server->push($frame->fd, '', \Swoole\WebSocket\Frame::OPCODE_PONG);
return;
}
// 处理普通文本消息...
$server->push($frame->fd, 'Received: ' . $frame->data);
});
$server->on('close', function ($server, $fd) {
echo "Client {$fd} disconnected\n";
});
$server->start();
⚠️ 注意:heartbeat_idle_time 和 heartbeat_check_interval 是 Swoole 内置心跳机制,依赖 TCP 层保活,不是 WebSocket 应用层 ping/pong,但能有效清理僵死连接。两者建议配合使用。
客户端配合要点
服务端有了机制,客户端也需主动维持连接:
- 浏览器 WebSocket 默认不自动发 ping,需 JS 手动定时
ws.send()一个简单字符串(如'ping'),或发二进制new Uint8Array([0x89])触发 ping - 更规范做法:用
ws.ping()(部分新版浏览器支持,非标准 API,慎用) - 推荐方案:客户端每 20 秒发一次业务无关消息(如
{"type":"heartbeat"}),服务端识别后不处理业务,仅刷新活跃时间
调试与验证方法
确认心跳生效的几个实用方式:
- 用
tcpdump或 Wireshark 抓包,过滤 WebSocket 流,观察是否有Opcode: Ping (9)/Pong (10)帧 - 服务端开启 Swoole 日志:
'log_file' => '/tmp/swoole.log', 'log_level' => SWOOLE_LOG_DEBUG,搜索ping/pong - 断网测试:客户端断网 30 秒后,观察服务端是否触发
onClose回调
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











