前言随着人工智能技术的爆发式发展大模型交互、实时数据分析、AI驱动的协同工具等场景日益普及流式传输技术的应用也愈发广泛。相较于传统的“请求-响应”完整数据返回模式流式传输能够实现数据的分段、实时推送大幅降低交互延迟、提升用户体验——例如AI对话机器人的逐字回复、实时语音转写的字幕同步、智能监控的实时告警推送等场景均离不开流式传输的支撑。WebSocket与SSE作为两种主流的流式传输实现方案分别适配全双工、单向推送的核心需求且均基于HTTP生态构建具备良好的兼容性与可落地性。理解这两种协议的底层原理、原生实现逻辑是开发者高效搭建AI流式应用、解决实时交互场景问题的基础。本文将彻底摒弃第三方库依赖聚焦Node.js http模块原生实现从协议原理、帧结构解析、代码落地到文档依据全方位拆解为技术开发与方案设计提供核心参考。1. WebSocket协议全双工通信实现1.1 协议核心原理通俗拆解WebSocket的核心价值是打破HTTP“一问一答”的束缚在客户端和服务器之间建立一条持久的“双向通话管道”适合实时场景。我们从3个关键环节通俗理解握手升级从HTTP“切换频道”客户端想和服务器建立WebSocket连接时会先发一条特殊的HTTP请求相当于说“我要切换到WebSocket频道”。请求头里必须带两个关键信息Upgrade: websocket声明要升级协议、Connection: Upgrade声明要保持连接。服务器同意后会返回101状态码表示“协议切换成功”自此双方不再用HTTP规则通信转而用WebSocket规则。帧格式通信高效“传包裹”切换成功后双方传输数据不再带繁琐的HTTP头而是把数据打包成“帧”类似快递包裹。每个帧都有明确标识操作码告诉对方这是文本/二进制/关闭连接等类型数据、掩码客户端发数据必须加密防止篡改、数据长度和内容。这种方式极大降低了传输开销适合高频实时数据。文档出处帧结构核心定义源自 RFC 6455 第5章Data Framing该章节详细规定了帧的字段构成、位含义及传输规则是帧原理的权威依据。保持连接心跳“保活”长时间不发数据的TCP连接可能被防火墙断开WebSocket用“Ping/Pong”心跳机制保活服务器发Ping帧给客户端客户端必须回Pong帧证明连接正常避免被强制断开。WebSocket是一种在单个TCP连接上提供全双工双向同时通信的应用层协议旨在解决HTTP协议“请求-响应”模式的单向性、短连接问题适用于实时聊天、实时协作等场景。其核心机制包括握手升级客户端通过HTTP请求发起协议升级请求头包含Upgrade: websocket、Connection: Upgrade等字段服务器响应101 Switching Protocols状态码完成从HTTP到WebSocket的协议切换。帧格式通信握手成功后双方以WebSocket帧为单位传输数据帧包含操作码文本/二进制/关闭等、掩码客户端发往服务器的数据必须掩码、数据长度及 payload 内容无需重复携带HTTP头降低开销。补充说明帧是WebSocket最小通信单元一个消息可由单个或多个帧组成分片传输帧结构严格遵循RFC 6455规范具体图示及字段含义如下保持连接通过Ping/Pong帧实现心跳检测避免TCP连接被中间设备如防火墙断开确保通信稳定性。WebSocket帧结构图示对应RFC 6455标准帧整体分为“帧头”最少2字节和“载荷数据”实际传输内容两部分各字段按位排列对应代码中帧解析逻辑图示如下文字描述适配技术文档嵌入可直接转化为可视化图表标准帧结构字节级拆解第1字节1位FIN 3位RSV1-RSV3 4位opcode第2字节1位MASK 7位Payload length可选字段4字节Masking-key仅客户端发数据时存在 载荷数据Payload data各字段含义对应代码解析逻辑FIN1位标识是否为消息的最后一帧1表示完整消息0表示分片帧。对应代码const fin (buffer[0] 0x80) 0x80通过位运算提取第1位值。RSV1-RSV3各1位预留字段默认0仅扩展协议时使用代码中暂不处理。opcode4位帧类型标识核心值0x01文本帧、0x02二进制帧、0x08关闭帧、0x09Ping帧、0x0APong帧。对应代码const opcode buffer[0] 0x0F提取低4位值。MASK1位标识载荷数据是否被掩码加密客户端发往服务器的帧必须设为1强制加密服务器发往客户端的帧设为0。对应代码const hasMask (buffer[1] 0x80) 0x80。Payloadlength7位载荷数据长度分三种情况0-125直接表示长度126表示后续2字节为长度127表示后续8字节为长度代码中仅处理0-125的短数据。对应代码let payloadLen buffer[1] 0x7F提取低7位值。Masking-key4字节仅MASK1时存在用于解密载荷数据代码中需通过异或运算解密之前乱码问题即未处理此步骤。参考图示来源除RFC 6455原文图示外可参考 MDN WebSocket数据帧格式 的可视化示意图更易理解字段对应关系。1.2 Node.js http模块实现WebSocketNode.js原生http模块可直接捕获协议升级请求通过自定义逻辑完成WebSocket握手、帧解析与数据传输这是理解WebSocket原理的核心方式。以下通过原生实现拆解每一步原理对应的代码逻辑不依赖任何第三方库直击协议本质。1.3 原生实现拆解原理对应代码以下原生代码完整实现握手升级、文本帧收发核心流程每一步均对应WebSocket原理同时标注生产环境需补充的原理细节如掩码、多帧处理帮你吃透协议底层逻辑。结合上述帧结构原理以下代码补充掩码解密逻辑解决乱码问题每一步解析均对应帧字段同时标注RFC规范依据实现原理与代码的深度绑定const http require(http); const crypto require(crypto); // 创建HTTP服务器WebSocket基于HTTP握手需先启动HTTP服务 const server http.createServer((req, res) { res.writeHead(200); res.end(Non-WebSocket request); }); // 监听upgrade事件对应【握手升级】原理捕获客户端升级请求 // 当客户端发带Upgrade: websocket的HTTP请求时触发此事件 server.on(upgrade, (req, socket, head) { // 1. 验证升级请求合法性原理确保是WebSocket协议升级请求 if (req.headers.upgrade ! websocket) { socket.write(HTTP/1.1 400 Bad Request\r\n\r\n); socket.destroy(); return; } // 2. 生成握手响应标识原理协议强制的身份验证机制防非法连接 const secWebSocketKey req.headers[sec-websocket-key]; // 客户端随机密钥 const magicString 258EAFA5-E914-47DA-95CA-C5AB0DC85B11; // 协议固定字符串 const hash crypto.createHash(sha1) .update(secWebSocketKey magicString) // 密钥与固定字符串拼接 .digest(base64); // 生成响应标识回传给客户端验证 // 3. 发送101响应完成握手升级原理HTTP协议切换为WebSocket协议 const responseHeaders [ HTTP/1.1 101 Switching Protocols, Upgrade: websocket, // 确认升级为WebSocket Connection: Upgrade, // 确认保持长连接 Sec-WebSocket-Accept: ${hash}, // 回传验证标识客户端校验通过则连接建立 \r\n ]; socket.write(responseHeaders.join(\r\n)); // 4. 监听socket数据解析WebSocket帧对应【帧格式通信】原理 // 握手成功后客户端发的数据以帧为单位传输需手动解析帧结构 socket.on(data, (buffer) { const fin (buffer[0] 0x80) 0x80; const opcode buffer[0] 0x0F; const hasMask (buffer[1] 0x80) 0x80; let payloadLen buffer[1] 0x7F; let payloadStart 2; // 数据起始位置默认帧头后 let maskKey []; // 步骤1提取掩码密钥客户端数据必带掩码 if (hasMask) { maskKey buffer.slice(payloadStart, payloadStart 4); payloadStart 4; // 数据起始位置后移4字节跳过掩码密钥 } // 步骤2解密数据异或运算 const payloadBuffer buffer.slice(payloadStart, payloadStart payloadLen); const decryptedPayload []; for (let i 0; i payloadBuffer.length; i) { decryptedPayload.push(payloadBuffer[i] ^ maskKey[i % 4]); // 异或解密 } const payload Buffer.from(decryptedPayload).toString(utf8); // 仅处理完整文本帧 if (opcode 1 fin) { console.log(Received:, payload); // 构建响应帧回传服务器发数据无需掩码 const responseBuffer Buffer.alloc(2 payload.length); responseBuffer[0] 0x81; responseBuffer[1] payload.length; responseBuffer.write(payload, 2); socket.write(responseBuffer); } }); // 连接关闭与错误处理避免资源泄漏 socket.on(close, () { console.log(WebSocket connection closed); }); socket.on(error, (err) { console.error(WebSocket error:, err); }); }); server.listen(8080, () { console.log(WebSocket server running on ws://localhost:8080); });客户端测试浏览器控制台const ws new WebSocket(ws://localhost:8080); ws.onopen () console.log(Connected); ws.send(Hello WebSocket); ws.onmessage (e) console.log(Received:, e.data); // 接收服务端响应1.4 WebSocket文档及协议标准协议规范RFC 6455 - The WebSocket Protocol WebSockets StandardIETF标准核心章节第4章握手流程、第5章帧结构与传输规则是帧原理与实现的最权威依据。MDN指南 WebSocket API - Web API | MDN2. SSE协议服务器向客户端单向推送2.1 协议核心原理通俗拆解SSE是一种“服务器单向发、客户端只接收”的轻量通信方式相当于服务器给客户端开了一个“实时广播频道”适合不需要客户端反馈的场景如通知、行情。核心逻辑比WebSocket简单基于HTTP长连接实现单向通信一条“只读管道”客户端只发一次GET请求服务器接收到后不关闭连接而是通过这个长连接持续往客户端推数据。客户端无法通过这个连接回发数据若需反馈只能再发一个HTTP请求。固定数据格式服务器“发消息的规矩”服务器推的数据必须满足两个要求响应头设为text/event-stream告诉客户端这是SSE流每条消息格式为“data:内容\n\n”双换行结尾标识一条消息结束还支持自定义事件名、消息ID。自动重连客户端“断联自愈”若连接意外断开如服务器重启客户端的EventSource API会自动重试连接默认3秒一次还能通过“消息ID”记录最后接收的消息重连后让服务器从断联处继续推实现断点续传。轻量无升级基于HTTP原生栈不需要像WebSocket那样切换协议完全复用HTTP机制实现简单、开销低适合对性能要求不极致但需快速落地的单向推送场景。Server-Sent EventsSSE是一种基于HTTP的单向通信协议仅支持服务器向客户端推送数据适用于实时通知、行情更新等无需客户端反馈的场景。其核心特性单向通信基于HTTP长连接客户端发起一次GET请求后服务器保持连接持续推送数据客户端无法向服务器发送数据需双向通信可结合HTTP请求补充。数据格式服务器推送的数据必须是text/event-stream类型每条消息以data:开头\n\n结尾支持事件名、ID、重试时间等扩展字段。自动重连客户端EventSource API在连接断开后会自动重连默认间隔3秒可通过retry:字段自定义重连间隔。轻量性无需协议升级基于现有HTTP栈实现简单开销低于WebSocket。2.2 Node.js http模块实现SSESSE无需第三方库可直接通过Node.js http模块实现核心是设置正确的响应头并持续推送格式化数据。const http require(http); const server http.createServer((req, res) { // 仅处理/sse路径请求作为SSE连接入口 if (req.url /sse) { // 第一步设置SSE核心响应头对应原理“固定数据格式”要求 res.writeHead(200, { Content-Type: text/event-stream, // 必须设为这个类型客户端才识别为SSE Cache-Control: no-cache, // 禁止缓存避免客户端重复接收旧数据 Connection: keep-alive, // 保持HTTP长连接不立即关闭 Access-Control-Allow-Origin: * // 跨域支持实际项目按需限制域名 }); // 第二步处理断点续传对应原理“自动重连” // 客户端重连时会携带Last-Event-ID头记录最后接收的消息ID const lastEventId req.headers[last-event-id] || 0; console.log(Last Event ID:, lastEventId); let eventId parseInt(lastEventId) 1; // 从断联处继续生成消息ID // 第三步定时推送消息模拟实时数据体现“单向持续推送” const interval setInterval(() { const data { time: new Date().toISOString(), content: SSE message #${eventId} }; // 构建SSE消息格式id可选 data必选 双换行结尾 const message [ id: ${eventId}, // 消息ID用于断点续传 data: ${JSON.stringify(data)}, // 消息内容必须以data:开头 \n // 空行双换行标识一条消息结束 ].join(\n); res.write(message); // 推送消息到客户端 eventId; // 模拟连接关闭可选实际场景可根据业务逻辑关闭 if (eventId 10) { clearInterval(interval); res.write(event: close\ndata: Connection closed\n\n); // 自定义关闭事件 res.end(); } }, 1000); // 第四步客户端断开连接时清理资源避免内存泄漏 req.on(close, () { clearInterval(interval); res.end(); console.log(SSE connection closed); }); } else { // 非SSE请求返回测试页面包含客户端EventSource逻辑 res.writeHead(200, { Content-Type: text/html }); res.end( SSE Test${e.data} ); } }); server.listen(8081, () { console.log(SSE server running on http://localhost:8081); });测试方式访问http://localhost:8081可看到每秒接收一条服务器推送的消息10条后连接自动关闭。2.3 SSE文档及协议标准协议规范RFC 8895 - Server-Sent Events(IETF标准替代旧版HTML5 SSE草案定义消息格式、重连机制)。MDN指南MDN Server-Sent Events客户端EventSource API、消息格式详解。3. WebSocket与SSE对比及适用场景特性WebSocketSSE通信方向全双工双向单向服务器→客户端协议基础HTTP握手升级为独立协议HTTP长连接无协议升级重连机制需手动实现如心跳检测客户端EventSource自动重连数据格式二进制/文本帧灵活高效仅文本text/event-stream适用场景实时聊天、协同编辑、游戏实时通知、行情推送、日志流4. 注意事项WebSocket跨域需在握手时处理Origin请求头或通过Nginx反向代理配置跨域。SSE缓存问题必须设置Cache-Control: no-cache否则客户端可能缓存推送数据。生产环境优化WebSocket需处理并发连接ws库支持集群部署SSE需限制单连接时长避免资源泄漏。兼容性WebSocket支持所有现代浏览器SSE在IE中不支持可通过EventSource polyfill兼容。团队介绍「智慧家技术平台-应用软件框架开发」主要负责设计工具的研发包括营销设计工具、家电VR设计和展示、水电暖通前置设计能力研发并沉淀素材库构建家居家装素材库集成户型库、全品类产品库、设计方案库、生产工艺模型打造基于户型和风格的AI设计能力快速生成算量和报价同时研发了门店设计师中心和项目中心包括设计师管理能力和项目经理管理能力。实现了场景全生命周期管理同时为水空气厨房等产业提供商机管理工具从而实现了以场景贯穿的B端C端全流程系统。
websocket及SSE原理解析
前言随着人工智能技术的爆发式发展大模型交互、实时数据分析、AI驱动的协同工具等场景日益普及流式传输技术的应用也愈发广泛。相较于传统的“请求-响应”完整数据返回模式流式传输能够实现数据的分段、实时推送大幅降低交互延迟、提升用户体验——例如AI对话机器人的逐字回复、实时语音转写的字幕同步、智能监控的实时告警推送等场景均离不开流式传输的支撑。WebSocket与SSE作为两种主流的流式传输实现方案分别适配全双工、单向推送的核心需求且均基于HTTP生态构建具备良好的兼容性与可落地性。理解这两种协议的底层原理、原生实现逻辑是开发者高效搭建AI流式应用、解决实时交互场景问题的基础。本文将彻底摒弃第三方库依赖聚焦Node.js http模块原生实现从协议原理、帧结构解析、代码落地到文档依据全方位拆解为技术开发与方案设计提供核心参考。1. WebSocket协议全双工通信实现1.1 协议核心原理通俗拆解WebSocket的核心价值是打破HTTP“一问一答”的束缚在客户端和服务器之间建立一条持久的“双向通话管道”适合实时场景。我们从3个关键环节通俗理解握手升级从HTTP“切换频道”客户端想和服务器建立WebSocket连接时会先发一条特殊的HTTP请求相当于说“我要切换到WebSocket频道”。请求头里必须带两个关键信息Upgrade: websocket声明要升级协议、Connection: Upgrade声明要保持连接。服务器同意后会返回101状态码表示“协议切换成功”自此双方不再用HTTP规则通信转而用WebSocket规则。帧格式通信高效“传包裹”切换成功后双方传输数据不再带繁琐的HTTP头而是把数据打包成“帧”类似快递包裹。每个帧都有明确标识操作码告诉对方这是文本/二进制/关闭连接等类型数据、掩码客户端发数据必须加密防止篡改、数据长度和内容。这种方式极大降低了传输开销适合高频实时数据。文档出处帧结构核心定义源自 RFC 6455 第5章Data Framing该章节详细规定了帧的字段构成、位含义及传输规则是帧原理的权威依据。保持连接心跳“保活”长时间不发数据的TCP连接可能被防火墙断开WebSocket用“Ping/Pong”心跳机制保活服务器发Ping帧给客户端客户端必须回Pong帧证明连接正常避免被强制断开。WebSocket是一种在单个TCP连接上提供全双工双向同时通信的应用层协议旨在解决HTTP协议“请求-响应”模式的单向性、短连接问题适用于实时聊天、实时协作等场景。其核心机制包括握手升级客户端通过HTTP请求发起协议升级请求头包含Upgrade: websocket、Connection: Upgrade等字段服务器响应101 Switching Protocols状态码完成从HTTP到WebSocket的协议切换。帧格式通信握手成功后双方以WebSocket帧为单位传输数据帧包含操作码文本/二进制/关闭等、掩码客户端发往服务器的数据必须掩码、数据长度及 payload 内容无需重复携带HTTP头降低开销。补充说明帧是WebSocket最小通信单元一个消息可由单个或多个帧组成分片传输帧结构严格遵循RFC 6455规范具体图示及字段含义如下保持连接通过Ping/Pong帧实现心跳检测避免TCP连接被中间设备如防火墙断开确保通信稳定性。WebSocket帧结构图示对应RFC 6455标准帧整体分为“帧头”最少2字节和“载荷数据”实际传输内容两部分各字段按位排列对应代码中帧解析逻辑图示如下文字描述适配技术文档嵌入可直接转化为可视化图表标准帧结构字节级拆解第1字节1位FIN 3位RSV1-RSV3 4位opcode第2字节1位MASK 7位Payload length可选字段4字节Masking-key仅客户端发数据时存在 载荷数据Payload data各字段含义对应代码解析逻辑FIN1位标识是否为消息的最后一帧1表示完整消息0表示分片帧。对应代码const fin (buffer[0] 0x80) 0x80通过位运算提取第1位值。RSV1-RSV3各1位预留字段默认0仅扩展协议时使用代码中暂不处理。opcode4位帧类型标识核心值0x01文本帧、0x02二进制帧、0x08关闭帧、0x09Ping帧、0x0APong帧。对应代码const opcode buffer[0] 0x0F提取低4位值。MASK1位标识载荷数据是否被掩码加密客户端发往服务器的帧必须设为1强制加密服务器发往客户端的帧设为0。对应代码const hasMask (buffer[1] 0x80) 0x80。Payloadlength7位载荷数据长度分三种情况0-125直接表示长度126表示后续2字节为长度127表示后续8字节为长度代码中仅处理0-125的短数据。对应代码let payloadLen buffer[1] 0x7F提取低7位值。Masking-key4字节仅MASK1时存在用于解密载荷数据代码中需通过异或运算解密之前乱码问题即未处理此步骤。参考图示来源除RFC 6455原文图示外可参考 MDN WebSocket数据帧格式 的可视化示意图更易理解字段对应关系。1.2 Node.js http模块实现WebSocketNode.js原生http模块可直接捕获协议升级请求通过自定义逻辑完成WebSocket握手、帧解析与数据传输这是理解WebSocket原理的核心方式。以下通过原生实现拆解每一步原理对应的代码逻辑不依赖任何第三方库直击协议本质。1.3 原生实现拆解原理对应代码以下原生代码完整实现握手升级、文本帧收发核心流程每一步均对应WebSocket原理同时标注生产环境需补充的原理细节如掩码、多帧处理帮你吃透协议底层逻辑。结合上述帧结构原理以下代码补充掩码解密逻辑解决乱码问题每一步解析均对应帧字段同时标注RFC规范依据实现原理与代码的深度绑定const http require(http); const crypto require(crypto); // 创建HTTP服务器WebSocket基于HTTP握手需先启动HTTP服务 const server http.createServer((req, res) { res.writeHead(200); res.end(Non-WebSocket request); }); // 监听upgrade事件对应【握手升级】原理捕获客户端升级请求 // 当客户端发带Upgrade: websocket的HTTP请求时触发此事件 server.on(upgrade, (req, socket, head) { // 1. 验证升级请求合法性原理确保是WebSocket协议升级请求 if (req.headers.upgrade ! websocket) { socket.write(HTTP/1.1 400 Bad Request\r\n\r\n); socket.destroy(); return; } // 2. 生成握手响应标识原理协议强制的身份验证机制防非法连接 const secWebSocketKey req.headers[sec-websocket-key]; // 客户端随机密钥 const magicString 258EAFA5-E914-47DA-95CA-C5AB0DC85B11; // 协议固定字符串 const hash crypto.createHash(sha1) .update(secWebSocketKey magicString) // 密钥与固定字符串拼接 .digest(base64); // 生成响应标识回传给客户端验证 // 3. 发送101响应完成握手升级原理HTTP协议切换为WebSocket协议 const responseHeaders [ HTTP/1.1 101 Switching Protocols, Upgrade: websocket, // 确认升级为WebSocket Connection: Upgrade, // 确认保持长连接 Sec-WebSocket-Accept: ${hash}, // 回传验证标识客户端校验通过则连接建立 \r\n ]; socket.write(responseHeaders.join(\r\n)); // 4. 监听socket数据解析WebSocket帧对应【帧格式通信】原理 // 握手成功后客户端发的数据以帧为单位传输需手动解析帧结构 socket.on(data, (buffer) { const fin (buffer[0] 0x80) 0x80; const opcode buffer[0] 0x0F; const hasMask (buffer[1] 0x80) 0x80; let payloadLen buffer[1] 0x7F; let payloadStart 2; // 数据起始位置默认帧头后 let maskKey []; // 步骤1提取掩码密钥客户端数据必带掩码 if (hasMask) { maskKey buffer.slice(payloadStart, payloadStart 4); payloadStart 4; // 数据起始位置后移4字节跳过掩码密钥 } // 步骤2解密数据异或运算 const payloadBuffer buffer.slice(payloadStart, payloadStart payloadLen); const decryptedPayload []; for (let i 0; i payloadBuffer.length; i) { decryptedPayload.push(payloadBuffer[i] ^ maskKey[i % 4]); // 异或解密 } const payload Buffer.from(decryptedPayload).toString(utf8); // 仅处理完整文本帧 if (opcode 1 fin) { console.log(Received:, payload); // 构建响应帧回传服务器发数据无需掩码 const responseBuffer Buffer.alloc(2 payload.length); responseBuffer[0] 0x81; responseBuffer[1] payload.length; responseBuffer.write(payload, 2); socket.write(responseBuffer); } }); // 连接关闭与错误处理避免资源泄漏 socket.on(close, () { console.log(WebSocket connection closed); }); socket.on(error, (err) { console.error(WebSocket error:, err); }); }); server.listen(8080, () { console.log(WebSocket server running on ws://localhost:8080); });客户端测试浏览器控制台const ws new WebSocket(ws://localhost:8080); ws.onopen () console.log(Connected); ws.send(Hello WebSocket); ws.onmessage (e) console.log(Received:, e.data); // 接收服务端响应1.4 WebSocket文档及协议标准协议规范RFC 6455 - The WebSocket Protocol WebSockets StandardIETF标准核心章节第4章握手流程、第5章帧结构与传输规则是帧原理与实现的最权威依据。MDN指南 WebSocket API - Web API | MDN2. SSE协议服务器向客户端单向推送2.1 协议核心原理通俗拆解SSE是一种“服务器单向发、客户端只接收”的轻量通信方式相当于服务器给客户端开了一个“实时广播频道”适合不需要客户端反馈的场景如通知、行情。核心逻辑比WebSocket简单基于HTTP长连接实现单向通信一条“只读管道”客户端只发一次GET请求服务器接收到后不关闭连接而是通过这个长连接持续往客户端推数据。客户端无法通过这个连接回发数据若需反馈只能再发一个HTTP请求。固定数据格式服务器“发消息的规矩”服务器推的数据必须满足两个要求响应头设为text/event-stream告诉客户端这是SSE流每条消息格式为“data:内容\n\n”双换行结尾标识一条消息结束还支持自定义事件名、消息ID。自动重连客户端“断联自愈”若连接意外断开如服务器重启客户端的EventSource API会自动重试连接默认3秒一次还能通过“消息ID”记录最后接收的消息重连后让服务器从断联处继续推实现断点续传。轻量无升级基于HTTP原生栈不需要像WebSocket那样切换协议完全复用HTTP机制实现简单、开销低适合对性能要求不极致但需快速落地的单向推送场景。Server-Sent EventsSSE是一种基于HTTP的单向通信协议仅支持服务器向客户端推送数据适用于实时通知、行情更新等无需客户端反馈的场景。其核心特性单向通信基于HTTP长连接客户端发起一次GET请求后服务器保持连接持续推送数据客户端无法向服务器发送数据需双向通信可结合HTTP请求补充。数据格式服务器推送的数据必须是text/event-stream类型每条消息以data:开头\n\n结尾支持事件名、ID、重试时间等扩展字段。自动重连客户端EventSource API在连接断开后会自动重连默认间隔3秒可通过retry:字段自定义重连间隔。轻量性无需协议升级基于现有HTTP栈实现简单开销低于WebSocket。2.2 Node.js http模块实现SSESSE无需第三方库可直接通过Node.js http模块实现核心是设置正确的响应头并持续推送格式化数据。const http require(http); const server http.createServer((req, res) { // 仅处理/sse路径请求作为SSE连接入口 if (req.url /sse) { // 第一步设置SSE核心响应头对应原理“固定数据格式”要求 res.writeHead(200, { Content-Type: text/event-stream, // 必须设为这个类型客户端才识别为SSE Cache-Control: no-cache, // 禁止缓存避免客户端重复接收旧数据 Connection: keep-alive, // 保持HTTP长连接不立即关闭 Access-Control-Allow-Origin: * // 跨域支持实际项目按需限制域名 }); // 第二步处理断点续传对应原理“自动重连” // 客户端重连时会携带Last-Event-ID头记录最后接收的消息ID const lastEventId req.headers[last-event-id] || 0; console.log(Last Event ID:, lastEventId); let eventId parseInt(lastEventId) 1; // 从断联处继续生成消息ID // 第三步定时推送消息模拟实时数据体现“单向持续推送” const interval setInterval(() { const data { time: new Date().toISOString(), content: SSE message #${eventId} }; // 构建SSE消息格式id可选 data必选 双换行结尾 const message [ id: ${eventId}, // 消息ID用于断点续传 data: ${JSON.stringify(data)}, // 消息内容必须以data:开头 \n // 空行双换行标识一条消息结束 ].join(\n); res.write(message); // 推送消息到客户端 eventId; // 模拟连接关闭可选实际场景可根据业务逻辑关闭 if (eventId 10) { clearInterval(interval); res.write(event: close\ndata: Connection closed\n\n); // 自定义关闭事件 res.end(); } }, 1000); // 第四步客户端断开连接时清理资源避免内存泄漏 req.on(close, () { clearInterval(interval); res.end(); console.log(SSE connection closed); }); } else { // 非SSE请求返回测试页面包含客户端EventSource逻辑 res.writeHead(200, { Content-Type: text/html }); res.end( SSE Test${e.data} ); } }); server.listen(8081, () { console.log(SSE server running on http://localhost:8081); });测试方式访问http://localhost:8081可看到每秒接收一条服务器推送的消息10条后连接自动关闭。2.3 SSE文档及协议标准协议规范RFC 8895 - Server-Sent Events(IETF标准替代旧版HTML5 SSE草案定义消息格式、重连机制)。MDN指南MDN Server-Sent Events客户端EventSource API、消息格式详解。3. WebSocket与SSE对比及适用场景特性WebSocketSSE通信方向全双工双向单向服务器→客户端协议基础HTTP握手升级为独立协议HTTP长连接无协议升级重连机制需手动实现如心跳检测客户端EventSource自动重连数据格式二进制/文本帧灵活高效仅文本text/event-stream适用场景实时聊天、协同编辑、游戏实时通知、行情推送、日志流4. 注意事项WebSocket跨域需在握手时处理Origin请求头或通过Nginx反向代理配置跨域。SSE缓存问题必须设置Cache-Control: no-cache否则客户端可能缓存推送数据。生产环境优化WebSocket需处理并发连接ws库支持集群部署SSE需限制单连接时长避免资源泄漏。兼容性WebSocket支持所有现代浏览器SSE在IE中不支持可通过EventSource polyfill兼容。团队介绍「智慧家技术平台-应用软件框架开发」主要负责设计工具的研发包括营销设计工具、家电VR设计和展示、水电暖通前置设计能力研发并沉淀素材库构建家居家装素材库集成户型库、全品类产品库、设计方案库、生产工艺模型打造基于户型和风格的AI设计能力快速生成算量和报价同时研发了门店设计师中心和项目中心包括设计师管理能力和项目经理管理能力。实现了场景全生命周期管理同时为水空气厨房等产业提供商机管理工具从而实现了以场景贯穿的B端C端全流程系统。