swoole方案 SSE (Server-Sent Events) 单向推送服务
·
浏览器和服务器建一条不断开的 HTTP 连接,服务器想推就推,浏览器收着。单向的,浏览器不能通过这条连接发消息回来。比 WebSocket
少握一次手,协议更简单。
---
代码
<?php
$server = new Swoole\Http\Server('0.0.0.0', 9502);
$server->on('request', function ($req, $res) use ($server) {
// SSE 必须的响应头
$res->header('Content-Type', 'text/event-stream');
$res->header('Cache-Control', 'no-cache');
$res->header('X-Accel-Buffering', 'no'); // 告诉 nginx 别缓冲
// 每秒推一次假股票数据
Swoole\Timer::tick(1000, function ($timerId) use ($res, $server) {
$data = json_encode([
'symbol' => 'AAPL',
'price' => round(150 + (mt_rand(-100, 100) / 100), 2),
'time' => date('H:i:s'),
]);
// SSE 格式固定:data: 内容\n\n
$ok = $res->write("data: $data\n\n");
// 客户端断了就停定时器
if (!$ok) Swoole\Timer::clear($timerId);
});
});
$server->start();
---
浏览器端(5行)
<script>
const es = new EventSource('http://localhost:9502');
es.onmessage = e => console.log(JSON.parse(e.data));
es.onerror = () => es.close();
</script>
---
解释
SSE 格式:就是普通 HTTP 响应,但不关闭连接,一直往里写 data: xxx\n\n,浏览器认识这个格式会自动触发 onmessage
$res->write():Swoole 的分块写,不调 end(),连接就不断
Timer::tick(1000, ...):每 1000ms 跑一次回调,不阻塞其他请求,Swoole 协程调度的
$ok = false:客户端关了标签页,write() 返回 false,这时候清掉定时器,不然一直在跑
---
测试
php server.php
# 终端看推送
curl -N http://localhost:9502
# 输出:
# data: {"symbol":"AAPL","price":150.42,"time":"14:23:01"}
# data: {"symbol":"AAPL","price":149.98,"time":"14:23:02"}
更多推荐

所有评论(0)