SSE(Server-Sent Events)
是HTML5的一项技术,它允许服务器单向地向浏览器发送数据。这种技术非常适合需要实时更新内容的应用,如股票行情、社交媒体更新、实时通知等。
SSE的特点
单向通信
:服务器向客户端发送数据,但客户端不能向服务器发送数据(与WebSockets不同,WebSockets是双向通信的)。持续连接
:客户端与服务器之间保持一个持续的连接,服务器可以在任何时候发送数据给客户端。自动重连
:如果连接断开,浏览器会自动尝试重新连接。
前端代码
<!DOCTYPE html>
<html>
<head>
<title>SSE demo</title>
</head>
<body>
<h1>Server-Sent Events</h1>
<div id="time"></div>
<script>
const eventSource = new EventSource('http://localhost:8000/events.php');
eventSource.onmessage = function(event) {
if(event.data==="closed"){
eventSource.close();
}
document.getElementById('time').innerHTML = event.data;
};
eventSource.onerror = function(err) {
console.error('EventSource error:', err);
};
eventSource.onopen = function(event) {
console.log('Connection opened');
};
</script>
</body>
</html>
后端Php代码
/Users/xxx/Sites/localhost/events.php
<?php
header("Access-Control-Allow-Origin: *");
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
$lastEventId = isset($_SERVER['HTTP_LAST_EVENT_ID']) ? intval($_SERVER['HTTP_LAST_EVENT_ID']) : 0;
function sendMsg($id, $msg) {
global $lastEventId;
echo "id: $id" . PHP_EOL;
if($msg!= "closed"){
foreach ($_GET as $key => $value) {
$msg .= " GET: $key: $value" . " ";
}
$msg .= " Last Event ID: $lastEventId" . " ";
}
echo "data: $msg" . PHP_EOL;
echo PHP_EOL;
ob_flush();
flush();
}
// 从上次的事件ID开始计数
$counter = $lastEventId;
echo "retry: 5000" . PHP_EOL; // 设置重连时间为5秒
while (true) {
sendMsg($counter, 'Server time: ' . date('H:i:s'));
sleep(1);
if ($counter % 10 == 0) {
$counter++;
sendMsg($counter, 'SSE connection closed by server');
break;
}
if($counter > 212) {
sendMsg($counter, 'closed');
}
$counter++;
}
命令行:php -S localhost:8000 -t /Users/xxx/Sites/localhost
断线重连
其他事件
在Server-Sent Events (SSE)
中,默认的事件类型是message
,但你可以自定义事件类型。除了默认的message事件之外,SSE还允许你定义并发送其他类型的事件。通过自定义事件类型,你可以在客户端区分处理不同类型的消息。
自定义事件类型
服务器端 PHP 示例代码
在服务器端,你可以通过在SSE流中指定事件类型来发送自定义事件。例如,使用event: <event_type>来指定事件类型。
<?php
header("Access-Control-Allow-Origin: *");
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
$lastEventId = isset($_SERVER['HTTP_LAST_EVENT_ID']) ? intval($_SERVER['HTTP_LAST_EVENT_ID']) : 0;
function sendMsg($id, $event, $msg) {
echo "id: $id" . PHP_EOL;
echo "event: $event" . PHP_EOL; // 指定事件类型
echo "data: " . json_encode($msg) . PHP_EOL;
echo PHP_EOL;
ob_flush();
flush();
}
$counter = $lastEventId;
echo "retry: 5000" . PHP_EOL; // 设置重连时间为5秒
while (true) {
if ($counter % 2 === 0) {
sendMsg($counter, 'custom-event', array('message' => 'Custom event', 'time' => date('H:i:s')));
} else {
sendMsg($counter, 'message', array('message' => 'Default message event', 'time' => date('H:i:s')));
}
if ($counter >= 10) {
sendMsg($counter, 'end', array('message' => 'SSE connection closed by server', 'time' => date('H:i:s')));
break;
}
sleep(1);
$counter++;
}
?>
客户端 JavaScript 示例代码
在客户端,你可以为自定义事件类型添加事件监听器。
<!DOCTYPE html>
<html>
<head>
<title>SSE Example</title>
</head>
<body>
<h1>Server-Sent Events</h1>
<div id="default"></div>
<div id="custom"></div>
<div id="end"></div>
<script>
const eventSource = new EventSource('http://your_domain.com/events');
eventSource.addEventListener('message', function(event) {
const data = JSON.parse(event.data);
document.getElementById('default').innerHTML = `Default event: ${data.message} at ${data.time}`;
console.log('Default event:', data);
});
eventSource.addEventListener('custom-event', function(event) {
const data = JSON.parse(event.data);
document.getElementById('custom').innerHTML = `Custom event: ${data.message} at ${data.time}`;
console.log('Custom event:', data);
});
eventSource.addEventListener('end', function(event) {
const data = JSON.parse(event.data);
document.getElementById('end').innerHTML = `End event: ${data.message} at ${data.time}`;
console.log('End event:', data);
eventSource.close();
});
eventSource.onerror = function(err) {
console.error('EventSource error:', err);
if (eventSource.readyState === EventSource.CLOSED) {
console.log('Connection was closed. Attempting to reconnect...');
}
};
eventSource.onopen = function(event) {
console.log('Connection opened');
};
</script>
</body>
</html>
4 comments
想想你的文章写的特别好https://www.ea55.com/
想想你的文章写的特别好https://www.237fa.com/
博主真是太厉害了!!!
zmbxat75803GT-图片和视频质量很好,不仅有文字内容,还有丰富的多媒体资源。http://m.ikaola.xyz//