← HTML5 video 视频元素 HTML5 应用缓存(Application Cache) →

HTML5 Server-Sent Events 实时通信

原创 2025-09-14 HTML5 已有人查阅

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);
    }
});

本节课程知识要点

  1. 连接建立:使用EventSource对象创建服务器连接

  2. 消息格式:服务器消息必须以"data:"开头,以"\n\n"结尾

  3. 事件类型:支持默认message事件和自定义事件

  4. 错误处理:实现onerror事件监听和自动重连机制

  5. 性能优化:合理设置消息频率和连接超时

  6. 安全考虑:实施CORS策略和身份验证机制

注意:本节课程超纲,初学者了解原理和用处即可!后续进阶教程学习完了再研究!

浏览器兼容性

浏览器 谷歌 浏览器 Chrome ie 浏览器 IE 火狐 浏览器 Firefox 欧朋 浏览器 Opera Safari 浏览器 Safari
是否支持 支持6+ 不支持 支持6+ 支持6+ 支持5+

性能优化建议

  1. 连接管理:及时关闭不再需要的连接

  2. 消息压缩:对大量数据使用压缩格式

  3. 心跳机制:定期发送心跳包保持连接活跃

  4. 批量更新:对频繁更新进行批量处理

  5. 资源清理:页面卸载时自动清理资源

安全注意事项

  1. CORS配置:正确设置跨域访问权限

  2. 身份验证:实现基于token的身份验证

  3. 数据验证:验证服务器发送的数据合法性

  4. HTTPS加密:生产环境使用HTTPS加密传输

通过Server-Sent Events技术,开发者可以构建高效的实时Web应用,为用户提供更加流畅和及时的交互体验。这种技术特别适合需要服务器主动推送数据的场景,如实时监控、消息通知、进度更新等应用。

← HTML5 video 视频元素 HTML5 应用缓存(Application Cache) →
分享笔记 (共有 篇笔记)
验证码:
微信公众号