Http短轮询、WebSocket与SSE三种通讯方式和它们之间的区别
创始人
2024-12-28 18:37:46
0

文章目录

    • 概要
    • Http
    • WebSocket
    • SSE
    • 小结

概要

本篇文章着重讲述了Http、WebSocket与SSE三种通讯方式的特点与实现方式以及它们之间的区别。

Http

  1. 短轮询(Short Polling)
  • 工作原理:一般是由客户端每隔一段时间(如每隔5s)向服务器发起一次普通 HTTP 请求,询问是否有新的数据,服务器响应后返回最新的数据。
  • 优点:简单易实现,支持跨浏览器,适用于低延迟要求不高的场景。
  • 缺点:会造成频繁的网络请求和服务器压力,无论有无新数据都会发起请求。

代码实现

function startPolling(url, interval=5000) {   setInterval(async () => {     try {       const response = await fetch(url);       if (!response.ok) {         throw new Error(`HTTP error! Status: ${response.status}`);       }       const data = await response.json();       console.log(data);     } catch (error) {       console.error(error);     }   }, interval); }   // 使用方法: startPolling('https://api.example.com/data', 5000); // 每5秒轮询一次  

这段代码定义了一个startPolling函数,它接收一个URL和轮询间隔(以毫秒为单位,默认5000毫秒)。使用setInterval来周期性地发送HTTP请求到指定的URL,并在收到响应后打印结果。如果发生错误,会在控制台中记录错误信息。

WebSocket

WebSocket是一种在单个TCP连接上进行全双工通信的协议。
webSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

  • 工作原理:Websocket 是一种全双工通信协议,通过建立持久连接,双方可以实时进行数据传输。
  • 优点:实时性更好,支持服务器主动推送数据,减少了不必要的请求开销。
  • 缺点:相对短轮询更复杂,对服务器和客户端都有一定的要求,可能受到网络限制。

代码实现
前端

 

nodejs(服务器)完整代码

var express = require('express'); var router = express.Router();  //引入ws模块 const WebSocket = require('ws').Server; const port = 3001;  //创建服务 const server = new WebSocket({ port }, () => {     console.log('webSocket服务开启'); })  const errorHandler = (error) => {     console.log('errorHandler====>客户端出错了', error) }  const closeHandler = (e) => {     console.log('closeHandler====>客户端断开了', e) } function messageHandler(data) {     console.log('messageHandler====>接收客户端消息', JSON.parse(data))     this.send(JSON.stringify(JSON.parse(data))) }  const connectHandler = (ws) => {     console.log('客户端已连接');     //监听客户端出错     ws.on('error', errorHandler);     //监听客户端断开链接     ws.on('close', closeHandler);     //监听客户端发来的消息     ws.on('message', messageHandler); } //建立连接 server.on('connection', connectHandler);  /* GET home page. */ router.get('/', function(req, res, next) {   res.render('index', { title: 'Express' }); });  module.exports = router; 

除了最基本的实现外,WebSocket还具有心跳检测机制与断线重连机制。

  • 心跳检测机制:一种用于检测系统、应用程序或网络连接状态的技术。基本原理是定期发送小型数据包(称为心跳包或心跳消息)以确认远程设备或连接仍然处于活动状态。如果一段时间内没有收到心跳响应,系统就会认为连接已断开或设备不再可用。服务端和客户端都会定时发送一段用于心跳检测的信息,如果能接受对方传递过来的信息,证明此时TCP连接正常,反正,则会认为连接已经终端,就会进入断线重连阶段。
  • 断线重连:当系统判断此时TCP连接中断后,就会开始重新开始自动从头建立TCP通道。

具体实现代码
前端

// Socket.js class Socket {     wsUrl: string = "";     constructor(url: string) {         this.wsUrl = url;     }     ModeCode = {         MSG: "message", // 普通消息         HEART_BETA: "heart_beta", // 心跳检测     };     ws: WebSocket;     webSocketState: boolean = false; // webSocket连接状态      heartBeta = {         time: 5 * 1000, //心跳检测间隔时间         timeout: 3 * 1000, //心跳超时间隔         reconnection: 10 * 1000, //断线重连时间     };     reconnectTimer;  // 断线重连时间器     connectWebSocket() {         this.ws = new WebSocket(this.wsUrl);         this.init();     }     // 初始化函数     init() {         this.ws.addEventListener("open", () => {             //ws状态设置为连接:true             this.webSocketState = true;             //是否启动心跳检测             this.heartBeta?.time                 ? this.startHeartBeta(this.heartBeta.time)                 : "";             console.log("开启连接");         });          this.ws.addEventListener('message', (e) => {             const data = JSON.parse(e.data);             switch (data.ModeCode) {                 case this.ModeCode.MSG:                     console.log("普通消息");                     break;                 case this.ModeCode.HEART_BETA:                     this.webSocketState = true;                     console.log("心跳消息", data.msg);                     break;             }         })          this.ws.addEventListener('error', (error) => {             this.webSocketState = false         })          this.ws.addEventListener("close", (e) => {             this.webSocketState = false;         });     }     // 心跳检测初始化     startHeartBeta(time: number) {         setTimeout(() => {             this.ws.send(                 JSON.stringify({ ModeCode: this.ModeCode, msg: new Date() })             );             this.waitingServer();         }, time);     }     // 延时等待服务端响应,通过webSocketState判断是否连线成功     waitingServer() {         this.webSocketState = false;         setTimeout(() => {             if (this.webSocketState) {                 this.startHeartBeta(this.heartBeta.time);             }             console.log("心跳无响应,已经断线了");              try {                 this.ws.close();             } catch (e) {                 console.log("连接已关闭");             }             this.reconnectWebSocket();         }, this.heartBeta.timeout);     }     // 重新连接     reconnectWebSocket() {         this.reconnectTimer = setTimeout(() => {             this.reconnectWs();         }, this.heartBeta.timeout);     }     reconnectWs() {         if (!this.ws) {  // 第一次执行,初始化             this.connectWebSocket()         }          if (this.ws && this.reconnectTimer) {             // 防止多个webSocket同时执行             clearTimeout(this.reconnectTimer)             this.reconnectTimer = null;             this.reconnectWebSocket()         }     } }  export default Socket; 

后端 node.js

var express = require('express'); var router = express.Router();  //引入ws模块 const WebSocket = require('ws').Server; const port = 3001;  //创建服务 const server = new WebSocket({ port }, () => {     console.log('webSocket服务开启'); })  const errorHandler = (error) => {     console.log('errorHandler====>客户端出错了', error) }  const closeHandler = (e) => {     console.log('closeHandler====>客户端断开了', e) } function messageHandler(data) {     console.log('messageHandler====>接收客户端消息', JSON.parse(data))     // this.send(JSON.stringify(JSON.parse(data)))     const { ModeCode } = JSON.parse(data)          switch (ModeCode) {         case 'message':             console.log('收到前端的消息');             break;         case 'heart_beta':             console.log('心跳检测');             this.send(JSON.stringify(JSON.parse(data)));             break         default:             break;     } }  const connectHandler = (ws) => {     console.log('客户端已连接');     //监听客户端出错     ws.on('error', errorHandler);     //监听客户端断开链接     ws.on('close', closeHandler);     //监听客户端发来的消息     ws.on('message', messageHandler); } //建立连接 server.on('connection', connectHandler);  /* GET home page. */ router.get('/', function(req, res, next) {   res.render('index', { title: 'Express' }); });  module.exports = router; 

SSE

Server-Sent Events(SSE)是一种用于实现服务器向客户端实时推送数据的Web技术。与传统的轮询和长轮询相比,SSE提供了更高效和实时的数据推送机制。严格地说,HTTP 协议是无法做到服务器主动推送信息。但是,有一种变通方法,那就是SSE。
SSE基于HTTP协议,允许服务器将数据以事件流(Event Stream)的形式发送给客户端。客户端通过建立持久的HTTP连接,并监听事件流,可以实时接收服务器推送的数据。

SSE与WebSocket 作用相似,但是WebSocket更强大和灵活。因为WebSocket是全双工通道,可以双向通信;SSE 是单向通道,只能服务器向浏览器发送。
和WebSocket相比SSE优点:

  • SSE 使用 HTTP 协议,现有的服务器软件都支持。WebSocket 是一个独立协议。
  • SSE 属于轻量级,使用简单;WebSocket协议相对复杂。
  • SSE 默认支持断线重连,WebSocket 需要自己实现。
  • SSE 一般只用来传送文本,二进制数据需要编码后传送,WebSocket 默认支持传送二进制数据。
  • SSE 支持自定义发送的消息类型。

代码实现:

   

小结

SSE与Http短轮训和WebSocket之间的区别就是其他两种通讯方式是双向的,而SSE则是服务端向客服端传输数据(单向的),例如ChatGPT。而短轮询相比WebSocket则适用于对实时性要求不高、数据更新频率较低的场景,例如一些简单的数据展示页面。WebSocket则适用于对实时性要求较高,需要频繁传输大量数据的场景,例如在线聊天、实时数据更新等。

相关内容

热门资讯

一分钟了解!wpk辅助透视辅助... 自定义新版wpk辅助系统规律,只需要输入自己想要的开挂功能,一键便可以生成出wpk辅助专用辅助器,不...
重大通报!微扑克脚本透明挂黑科... 自定义新版系统规律,只需要输入自己想要的开挂功能,一键便可以生成出专用辅助器,不管你是想分享给你好友...
揭秘几款!微扑克wpk插件外挂... 揭秘几款!微扑克wpk插件外挂透明挂!微扑克wpk插件外挂辅助挂(2021已更新)(哔哩哔哩);1、...
一秒答解!微扑克ai外挂透明挂... 一秒答解!微扑克ai外挂透明挂辅助!微扑克ai外挂辅助器(2022已更新)(哔哩哔哩)是一款可以让一...
科普!微扑克系统透明挂辅助!微... 科普!微扑克系统透明挂辅助!微扑克系统辅助插件(2022已更新)(哔哩哔哩)是一款可以让一直输的玩家...
第三方教程!wepoke ap... 第三方教程!wepoke app透明挂测试!wepoke app辅助工具(2023已更新)(哔哩哔哩...
我来教大家!wepoke ap... 自定义新版系统规律,只需要输入自己想要的开挂功能,一键便可以生成出专用辅助器,不管你是想分享给你好友...
wepoke教程!wepoke... wepoke教程!wepoke黑科技透明挂神器!wepoke黑科技辅助神器(2021已更新)(哔哩哔...
存在挂教程!wepoke科技透... 存在挂教程!wepoke科技透明挂!wepoke科技辅助技巧(2020已更新)(哔哩哔哩);AI智能...
关于!微扑克规律透明挂测试!微... 关于!微扑克规律透明挂测试!微扑克规律开挂辅助(2023已更新)(哔哩哔哩)是一款可以让一直输的玩家...