当前位置: 首页 > news >正文

客户端与服务端实时通讯(轮询、websocket、SSE)

客户端与服务端实时通讯

背景

在某些项目中,某些数据需要展示最新的,实时的,这时候就需要和服务端进行长时间通讯

方案

对于数据实时获取,我们一般会有4种方案:

1.短轮询:使用浏览器的定时器发起http请求,每隔一段时间就请求一次
2.长轮询:客户端向服务器发送Ajax请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。
3.websocket:客户端与服务端建立websocket连接,搭建双工(双向)通道
4.SSE(Server-Sent Events):基于HTTP的html5新特性,服务器推送,属于半双工通信模型

轮询

轮询是指客户端定时向服务器发送ajax请求,服务器接到请求后马上返回响应信息并关闭连接。

轮询分为短轮询和长轮询

短轮询

实现原理: 短轮询指客户端每间隔一段时间向服务端发起请求,保持数据的同步。

优点: 可实现基础(指间隔时间较短)的数据更新。

缺点: 这种方法也只是尽量的模拟即时传输,但并非真正意义上的即时通讯,坏处是间隔设置的太长用户体验不好,设置间隔太短后端服务会进行大量的无效查询并且数据没有及时返回前端展示给用户。

长轮询

实现原理: 客户端发送请求后,如果没有数据返回,服务端会将请求放入队列一直连接处理其他请求,直到有数据才返回给客户端,然后客户端再次发起请求,以此轮询。在 HTTP1.0 中客户端可以设置请求头 Connection:keep-alive,服务端收到该请求头之后知道这是一个长连接,在响应报文头中也添加 Connection:keep-alive。客户端收到之后表示长连接建立完成,可以继续发送其他的请求。在 HTTP1.1 中默认使用了 Connection:keep-alive 长连接。
优点: 减少了大量无效的查询,保证每次请求都有数据返回,不会一直占用线程。
缺点: 如果新数据频繁,会进行大量的连接建立和关闭,对服务器的处理能力要求较高。服务器一直保持连接会消耗资源,需要同时维护多个线程,服务器所能承载的 TCP 连接数是有上限的,这种轮询很容易把连接数顶满。每次通讯都需要客户端发起,服务端不能主动推送。

websocket

实现原理: Websocket 实现了客户端与服务端的双向(双工)通信,只需要连接一次,就可以相互传输数据,很适合实时通讯、数据实时更新等场景。
优点:
1.双向通讯:客户端服务端双方都可以主动发起通讯
2.没有同源限制:相对于tcp请求websocket客户端可以与任意服务端通讯,不存在跨域的情况
3.数据量轻:只需要第一次连接时携带请求头,后面的数据通讯都不需要携带请求头
4.传输效率高,因为只需要一次连接
缺点:
1.长连接需要后端处理业务的代码更稳定,推送消息相对复杂
2.长连接对网络要求比较大,需要处理好重连接
3.兼容性差,Websocket只支持IE10及以上

使用

1.客户端代码

  <script>let socket = new WebSocket('ws://localhost:8888')socket.onopen = function () {console.log('1. 客户端连接上了服务器',new Date().getTime());socket.send('3. 你好')}socket.onmessage = function (e) {console.log('6',e.data);}
</script>

2.服务端代码

let express = require('express')
let app = express()
app.use(express.static(__dirname))app.listen(3000)let WebSocket = require('ws')
let wss = new WebSocket.Server({port:8888})
wss.on('connection',function(ws){console.log('2.服务器监听到了客户端的连接',new Date().getTime());ws.on('message',function(data){console.log('4.客户端发来的消息',data);ws.send('5.服务端说:你也好')})
})

SSE(EventSource)

实现原理: 客户端首先向服务器发送一个 HTTP 请求,然后服务器设置响应头并保持这个连接打开,并周期性地通过这个连接向客户端发送数据。每个数据块都是一个独立的消息。

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

优点:
1.简单易用:只需要在客户端创建一个EventSource对象,指定服务器端的URL,即可进行监听并展示事件。
2.网络带宽节省:EventSource采用长连接的方式进行数据传输,相比于普通的轮询方式,能够节省大量的网络带宽。
3.跨域支持:允许在跨域环境下进行通信,通过适当的响应头授权来自不同域的客户端连接。
缺点:
1.单项通信:只支持服务器向客户端的单向通信,无法实现客户端向服务器的实时交互。
2.不能重连:如果网络连接不稳定,或者服务器端关闭EventStream连接,客户端需要重新连接才能继续监听事件。
3.不支持二进制数据传输:只能传输文本数据,不能传输二进制数据,这在某些场景下可能存在一定的局限性。

使用

1.客户端

var eventSource = new EventSource("/clock");
eventSource.onmessage = function(event) {console.log("Received event: " + event.data);
};

2.服务端

let express = require('express')
let app = express()
app.use(express.static(__dirname))let counter = 0
app.get('/clock',function(req,res){res.header('Content-Type','text/event-stream')let $timer = setInterval(() => {// 第一种写法res.write(`id:${counter++}\nevent:message\ndata:${new Date().toLocaleString()}\n\n`)// 另一种写法res.write(`event:yya\n`)     // 触发 自定义事件res.write(`data:${counter}\n\n`)}, 1000 );res.on('close',function(){counter = 0clearInterval($timer)})
})
app.listen(3000)

chatGPT就是使用的这种方式
请添加图片描述
响应头
在这里插入图片描述
响应的数据
在这里插入图片描述

相关文章:

  • Android 11.0 禁用adb remount功能的实现
  • YOLOv5:修改backbone为SPPCSPC
  • Cross-Entropy Loss(多分类损失函数)
  • Linux-bluetooth蓝牙
  • JAVA安全入门之反射
  • mfc140u.dll丢失怎么修复,mfc140u.dll文件有什么作用
  • Android开发知识学习——Kotlin进阶
  • 科学化决策数据分析,先从量化开始
  • .net 写了一个支持重试、熔断和超时策略的 HttpClient 实例池
  • 【Linux】第六站:Centos系统如何安装软件?
  • GCC 编译器 详细总结
  • 刷题笔记day08-字符串01
  • 编译支持GPU的opencv,并供python的import cv2调用
  • 程序员想要网上接单却看花了眼?那这几个平台你可得收藏好了!
  • C++之初始化列表详细剖析
  • __proto__ 和 prototype的关系
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • Druid 在有赞的实践
  • Essential Studio for ASP.NET Web Forms 2017 v2,新增自定义树形网格工具栏
  • in typeof instanceof ===这些运算符有什么作用
  • JavaScript实现分页效果
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • Terraform入门 - 3. 变更基础设施
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 基于Javascript, Springboot的管理系统报表查询页面代码设计
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 记一次删除Git记录中的大文件的过程
  • 聊聊redis的数据结构的应用
  • 前嗅ForeSpider中数据浏览界面介绍
  • 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域
  • 双管齐下,VMware的容器新战略
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • 组复制官方翻译九、Group Replication Technical Details
  • ​2020 年大前端技术趋势解读
  • ​linux启动进程的方式
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (考研湖科大教书匠计算机网络)第一章概述-第五节1:计算机网络体系结构之分层思想和举例
  • (六)软件测试分工
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (转)母版页和相对路径
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • .NET Framework杂记
  • .NET/C# 检测电脑上安装的 .NET Framework 的版本
  • .NET开发不可不知、不可不用的辅助类(一)
  • .NET项目中存在多个web.config文件时的加载顺序
  • .NET中winform传递参数至Url并获得返回值或文件
  • /run/containerd/containerd.sock connect: connection refused
  • @RequestBody与@ModelAttribute
  • @Responsebody与@RequestBody
  • [ 云计算 | AWS ] 对比分析:Amazon SNS 与 SQS 消息服务的异同与选择
  • [2021 蓝帽杯] One Pointer PHP
  • [Android 数据通信] android cmwap接入点
  • [AutoSar]工程中的cpuload陷阱(三)测试
  • [boost]使用boost::function和boost::bind产生的down机一例