一、1分钟核心选型:SSE vs WebSocket
先记住一句话:单向推送用SSE,双向交互用WebSocket
核心区别(开发必看)
| 特性 | SSE (Server-Sent Events) | WebSocket |
|---|---|---|
| 通信方向 | 服务端 → 客户端 单向 | 服务端 ↔ 客户端 全双工双向 |
| 连接类型 | 基于 HTTP 长连接 | 独立协议(ws/wss) |
| 重连机制 | 浏览器自动重连(无需写代码) | 必须手动实现重连 |
| 数据格式 | 纯文本(JSON/字符串) | 文本/二进制都支持 |
| 开发成本 | 极低(PHP原生就能写) | 高(需要服务端守护进程/扩展) |
| 适用场景 | 通知、日志、实时榜单、进度条 | 聊天、游戏、协同编辑、直播互动 |
| 跨域 | 支持(需配置header) | 支持 |
什么时候必须选 SSE?
- 只需要服务端主动推消息给前端
- 不想折腾复杂的 WebSocket 服务
- 需要断线自动重连
- 技术栈是 PHP/Java/Python 这种传统 Web 语言
- 场景:订单通知、系统公告、实时日志、数据监控、上传/导出进度条
什么时候必须选 WebSocket?
- 前端需要频繁主动发消息给服务端
- 需要低延迟双向交互
- 场景:在线聊天、游戏、多人协作、直播弹幕
二、SSE 核心特性 & 实际开发场景
SSE 核心知识点(必须掌握)
- Content-Type: text/event-stream:SSE 固定响应头
- 长连接:连接保持打开,服务端持续输出数据
- 自动重连:断开后浏览器默认3秒重连,无需前端处理
- 消息格式:必须以
data: 内容\n\n结尾(两个换行是协议规定) - 支持自定义事件、消息ID(用于断线续传)
最常用的 SSE 实际业务场景
- 实时消息通知(后台有新订单/新消息推前端)
- 系统日志实时展示(部署日志、运行日志)
- 数据实时刷新(监控面板、实时榜单)
- 任务进度条(文件导出、批量处理、上传进度)
- 公告/广播推送(全员推送系统消息)
三、PHP 实现 SSE 完整代码示例
环境要求
- PHP 5.4+ / 7.x / 8.x 均可
- 关闭输出缓存(关键!)
- Nginx/Apache 默认配置即可
示例1:基础版 SSE(持续推送时间)
最简单、可直接运行的入门代码
后端:sse_server.php
<?php
// 禁用缓存
header('Cache-Control: no-cache');
// SSE 核心响应头
header('Content-Type: text/event-stream');
header('Connection: keep-alive');
// 跨域配置(前端不同域名必须加)
header('Access-Control-Allow-Origin: *');
// 无限循环推送消息
while (true) {
$time = date('Y-m-d H:i:s');
// SSE 固定格式:data: 内容\n\n
echo "data: 当前服务器时间:{$time}\n\n";
// 刷新缓冲区,把数据推送给前端
ob_flush();
flush();
// 每2秒推送一次
sleep(2);
}
?>前端:index.html
<!DOCTYPE html>
<html>
<head>
<title>SSE 基础示例</title>
</head>
<body>
<h3>实时消息:</h3>
<div id="msg"></div>
<script>
// 创建 SSE 连接
const sse = new EventSource('sse_server.php');
// 接收消息
sse.onmessage = function (e) {
document.getElementById('msg').innerHTML += e.data + '<br>';
};
// 错误监听(断网/服务挂了会自动重连)
sse.onerror = function () {
console.log('连接异常,浏览器自动重连中...');
};
</script>
</body>
</html>运行效果:前端每2秒自动收到服务端时间,断开网络重连后自动恢复。
示例2:JSON 数据推送(开发真实场景)
开发中90%都是推 JSON 数据(订单、通知、列表等)
后端:sse_json.php
<?php
header('Cache-Control: no-cache');
header('Content-Type: text/event-stream');
header('Connection: keep-alive');
header('Access-Control-Allow-Origin: *');
// 模拟订单数据
$orders = [
['id' => 1001, 'title' => '新订单', 'price' => 99.9],
['id' => 1002, 'title' => '支付成功', 'price' => 199.9]
];
while (true) {
// 随机取一条订单
$order = $orders[array_rand($orders)];
$order['time'] = date('H:i:s');
// 推送 JSON 格式
echo "data: " . json_encode($order) . "\n\n";
ob_flush();
flush();
sleep(3);
}
?>前端接收 JSON
const sse = new EventSource('sse_json.php');
sse.onmessage = function (e) {
// 解析 JSON
const data = JSON.parse(e.data);
console.log('订单通知:', data);
alert(`新订单:${data.title} - ${data.price}元`);
};示例3:实战场景 —— 任务进度条推送
最常用的业务:文件导出、批量处理、上传进度
后端:sse_progress.php
<?php
header('Cache-Control: no-cache');
header('Content-Type: text/event-stream');
header('Connection: keep-alive');
// 模拟任务进度 0% → 100%
$progress = 0;
while ($progress <= 100) {
// 推送进度
echo "data: {$progress}\n\n";
ob_flush();
flush();
$progress += 10; // 每次加10%
sleep(1);
}
// 完成信号
echo "data: finish\n\n";
ob_flush();
flush();
?>前端进度条
<div style="width: 300px; background: #eee;">
<div id="bar" style="width: 0%; height: 20px; background: green;"></div>
</div>
<p id="text">0%</p>
<script>
const sse = new EventSource('sse_progress.php');
sse.onmessage = function(e) {
const p = e.data;
if (p === 'finish') {
document.getElementById('text').innerText = '任务完成!';
sse.close(); // 关闭连接
return;
}
document.getElementById('bar').style.width = p + '%';
document.getElementById('text').innerText = p + '%';
};
</script>四、PHP + SSE 开发关键避坑点
- 必须关闭输出缓存
ob_flush()+flush()必须同时写,否则消息推不出去 - 无限循环不要占用过高资源
必须加sleep(1)或更长间隔,避免CPU占满 Nginx 环境配置
如发现消息不推送,在 Nginx 配置加:proxy_buffering off;- SSE 是单工通道
前端不能通过 SSE 发消息给后端(要用AJAX/axios)
五、最终总结(记住这3点就够)
- 选型口诀:单向推送选SSE,双向交互选WebSocket
- SSE优势:基于HTTP、自动重连、PHP零成本实现、开发极快
- 适用场景:通知、日志、实时数据、进度条、广播
你现在可以直接复制上面的代码运行,马上就能体验 SSE 实时推送效果。
评论 (0)