HTML5 Server-Sent Events 实时通信教程
Server-Sent Events(SSE)是HTML5提供的服务器推送技术,允许服务器主动向客户端发送数据,建立单向实时通信通道。与传统的轮询和长轮询相比,SSE提供了更高效的实时数据更新解决方案。
技术原理
SSE工作机制
SSE基于HTTP协议,通过保持一个持久连接,使服务器能够随时向客户端推送数据。这种单向通信模式特别适合需要实时更新的应用场景。
与传统Ajax对比
| 特性 | XMLHttpRequest | Server-Sent Events |
|---|---|---|
| 通信方向 | 双向 | 单向(服务器→客户端) |
| 连接方式 | 短连接 | 持久连接 |
| 实时性 | 需要轮询 | 实时推送 |
| 协议基础 | HTTP请求/响应 | HTTP流式传输 |
服务器端实现
Node.js 示例
// server.js - Node.js Express 服务器
const express = require('express');
const app = express();
app.get('/sse-stream', (req, res) => {
// 设置SSE必需的响应头
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
res.setHeader('Access-Control-Allow-Origin', '*');
// 定时发送数据
let counter = 0;
const intervalId = setInterval(() => {
counter++;
const currentTime = new Date().toLocaleTimeString();
// SSE消息格式
res.write(`data: ${JSON.stringify({
id: counter,
time: currentTime,
message: "代码号编程学习平台实时更新",
progress: Math.min(counter * 10, 100)
})}\n\n`);
// 模拟发送10次后关闭连接
if (counter >= 10) {
clearInterval(intervalId);
res.write('event: close\ndata: 连接关闭\n\n');
res.end();
}
}, 2000);
// 处理连接关闭
req.on('close', () => {
clearInterval(intervalId);
res.end();
});
});
app.listen(3000, () => {
console.log('SSE服务器运行在端口3000');
});
PHP 示例
<?php
// sse-server.php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header('Access-Control-Allow-Origin: *');
// 禁用输出缓冲
if (function_exists('apache_setenv')) {
apache_setenv('no-gzip', '1');
}
ini_set('zlib.output_compression', 0);
ini_set('implicit_flush', 1);
$counter = 0;
while ($counter < 10) {
$counter++;
$currentTime = date('H:i:s');
$data = [
'id' => $counter,
'time' => $currentTime,
'content' => '代码号教程更新通知',
'type' => 'learning_progress'
];
echo "data: " . json_encode($data) . "\n\n";
ob_flush();
flush();
// 如果连接中断则退出循环
if (connection_aborted()) break;
sleep(2);
}
echo "event: end\ndata: 传输完成\n\n";
ob_flush();
flush();
?>
客户端实现
基本事件监听
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>代码号编程学习进度实时监控</title>
<style>
.sse-container {
max-width: 800px;
margin: 20px auto;
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
}
.progress-bar {
height: 20px;
background-color: #f0f0f0;
border-radius: 10px;
margin: 10px 0;
overflow: hidden;
}
.progress-fill {
height: 100%;
background-color: #4CAF50;
width: 0%;
transition: width 0.5s ease;
}
.event-log {
height: 200px;
overflow-y: auto;
border: 1px solid #ccc;
padding: 10px;
margin-top: 20px;
font-family: monospace;
}
</style>
</head>
<body>
<div class="sse-container">
<h2>代码号学习平台实时进度</h2>
<img src="https://www.ebingou.cn/biancheng/images/logo.png" alt="代码号logo" height="40">
<div class="progress-container">
<h3>学习进度: <span id="progressPercent">0%</span></h3>
<div class="progress-bar">
<div class="progress-fill" id="progressFill"></div>
</div>
</div>
<div class="real-time-data">
<h4>实时数据流</h4>
<div class="event-log" id="eventLog"></div>
</div>
<button onclick="connectSSE()">开始连接</button>
<button onclick="disconnectSSE()">断开连接</button>
</div>
<script>
let eventSource = null;
function connectSSE() {
if (eventSource) {
console.log('SSE连接已存在');
return;
}
// 创建EventSource实例
eventSource = new EventSource('http://localhost:3000/sse-stream');
// 监听消息事件
eventSource.onmessage = function(event) {
const data = JSON.parse(event.data);
updateUI(data);
logEvent(`收到消息: ${JSON.stringify(data)}`);
};
// 监听自定义事件
eventSource.addEventListener('close', function(event) {
logEvent(`服务器通知: ${event.data}`);
disconnectSSE();
});
// 监听连接打开事件
eventSource.onopen = function() {
logEvent('SSE连接已建立');
};
// 监听错误事件
eventSource.onerror = function(error) {
logEvent('连接错误: ' + JSON.stringify(error));
disconnectSSE();
};
}
function disconnectSSE() {
if (eventSource) {
eventSource.close();
eventSource = null;
logEvent('SSE连接已关闭');
}
}
function updateUI(data) {
document.getElementById('progressPercent').textContent = data.progress + '%';
document.getElementById('progressFill').style.width = data.progress + '%';
}
function logEvent(message) {
const logElement = document.getElementById('eventLog');
const timestamp = new Date().toLocaleTimeString();
logElement.innerHTML += `[${timestamp}] ${message}<br>`;
logElement.scrollTop = logElement.scrollHeight;
}
// 页面卸载时自动关闭连接
window.addEventListener('beforeunload', disconnectSSE);
</script>
</body>
</html>
高级功能实现
自定义事件类型
// 服务器端 - 发送自定义事件
res.write("event: userUpdate\n");
res.write(`data: ${JSON.stringify({
userId: "123",
username: "代码号学员",
action: "completed_lesson",
lesson: "HTML5高级教程"
})}\n\n`);
// 客户端 - 监听自定义事件
eventSource.addEventListener('userUpdate', function(event) {
const userData = JSON.parse(event.data);
console.log('用户更新:', userData);
showNotification(`${userData.username} 完成了 ${userData.lesson}`);
});
重连机制
// 自动重连实现
let reconnectAttempts = 0;
const maxReconnectAttempts = 5;
function createEventSource() {
eventSource = new EventSource('/sse-stream');
eventSource.onerror = function() {
if (reconnectAttempts < maxReconnectAttempts) {
reconnectAttempts++;
setTimeout(createEventSource, 2000 * reconnectAttempts);
}
};
eventSource.onopen = function() {
reconnectAttempts = 0; // 重置重连计数
};
}
实际应用场景
实时学习进度跟踪
// 学习平台实时监控
eventSource.addEventListener('learningProgress', function(event) {
const progressData = JSON.parse(event.data);
updateProgressChart(progressData);
updateLeaderboard(progressData);
sendAchievementNotifications(progressData);
});
function updateProgressChart(data) {
// 更新学习进度图表
const ctx = document.getElementById('progressChart').getContext('2d');
// 图表更新逻辑...
}
多人协作编程环境
// 实时代码协作
eventSource.addEventListener('codeUpdate', function(event) {
const codeUpdate = JSON.parse(event.data);
if (codeUpdate.userId !== currentUserId) {
applyRemoteCodeChanges(codeUpdate.changes);
showCollaboratorActivity(codeUpdate.userName);
}
});
本节课程知识要点
-
连接建立:使用EventSource对象创建服务器连接
-
消息格式:服务器消息必须以"data:"开头,以"\n\n"结尾
-
事件类型:支持默认message事件和自定义事件
-
错误处理:实现onerror事件监听和自动重连机制
-
性能优化:合理设置消息频率和连接超时
-
安全考虑:实施CORS策略和身份验证机制
注意:本节课程超纲,初学者了解原理和用处即可!后续进阶教程学习完了再研究!
浏览器兼容性
| 浏览器 | Chrome |
IE |
Firefox |
Opera |
Safari |
| 是否支持 | 支持6+ | 不支持 | 支持6+ | 支持6+ | 支持5+ |
性能优化建议
-
连接管理:及时关闭不再需要的连接
-
消息压缩:对大量数据使用压缩格式
-
心跳机制:定期发送心跳包保持连接活跃
-
批量更新:对频繁更新进行批量处理
-
资源清理:页面卸载时自动清理资源
安全注意事项
-
CORS配置:正确设置跨域访问权限
-
身份验证:实现基于token的身份验证
-
数据验证:验证服务器发送的数据合法性
-
HTTPS加密:生产环境使用HTTPS加密传输
通过Server-Sent Events技术,开发者可以构建高效的实时Web应用,为用户提供更加流畅和及时的交互体验。这种技术特别适合需要服务器主动推送数据的场景,如实时监控、消息通知、进度更新等应用。
Chrome
IE
Firefox
Opera
Safari