文章目录

  • 一、SSE
    • 使用场景
    • 服务端响应示例
    • 浏览器处理服务器返回数据
    • SSE使用注意事项
    • 使用示例
  • 二、轮询
  • 三、WebSocket
    • 什么是Socket?什么是WebSocket?
    • 那么他是如何建立连接?如何进行数据交换?如何维持连接呢?

SSE(Server-Sent Events): 通俗说就是一种基于HTTP的,以流的形式由服务端持续向客户端发送数据的技术。

一、SSE

服务器发送事件,是基于http协议,和WebSocket全双工通道(web端和服务端相互通信)相比,SSE单通道(服务端推送数据到客户端)。是HTML 5规范的一个组成部分。

使用场景

  • 新邮件提示
  • 视频直播
  • 监控系统的实时数据。

web端消息推送功能中,由于传统的HTTP协议是由客户端主动发起请求,服务端才会响应。基本的ajax轮询技术便是如此。而在SSE中,浏览发送一个请求给服务端,通过响应头中的Content-Type:text/event-stream向客户端声名这是一个长连接,发送的是流数据,这样客户端就不会关闭连接,一直等待服务端发送数据

服务端响应示例

//如下,每个事件通过空行来分隔,对于每一行来说, 冒号前表示的是该行的类型,冒号后面是对应的值
data: first event //类型为data, 表示改行表示的是数据,以data开头的行可以多次出现,都是该事件中的数据data: second event
id: 001event: myevent //类型为event,表示用来声名事件类型,浏览器收到该事件时,会产生对应类型的事件.如果没有该字段,会产生默认类型
data: third event
id: 002 //id,用来声名事件标识符: this is a comment //类型为空白,表示该行是注释,回在处理时被忽略
data: fourth event
data: fourth event continue
retry: 1000 //表示该行用来声明浏览器在连接断开之后进行再次连接之前的等待时间

如果服务器返回的数据中包含了事件标识符浏览器会记录最后一次接收的事件的标识符。如果与服务器的连接中断,当浏览器再次进行连接时,会通过httpLast-Event-ID来声明最后一次接收的事件的标识符。服务器端可以通过浏览器发送的事件标识符来确定从哪个事件来继续连接。

浏览器处理服务器返回数据

对于服务端返回的响应,浏览器端需要在js中使用EventSource对象来进行处理。EventSource使用的是标准的事件监听方式:只需要在对象上添加对应的处理方法即可。EventSource提供的三个标准事件:

名称 说明 事件处理方法
open 成功与服务器建立连接时产生 onopen
message 收到服务器发送的事件时产生 onmessage
error 出现错误时产生 onerroe

如果服务器端返回自定义类型的事件,对于这些事件可以使用addEventListener方法来添加相应的事件处理方法,例如:

let es = new EnventSource('events');
//标准事件
es.onmessage = function (e) {console.log(e.data);
};
//自定义事件
es.addEventListener('myevent', function(e){console.log(e.data);
})

SSE使用注意事项

  1. 如何保证数据的完整性
    客户端在每次接收到消息时,会把消息的id 字段作为内部属性 Last-Event-ID储存起来。SSE默认支持断线重连机制,在连接断开时会 触发EventSourceerror事件,同时自动重连。再次连接成功时 EventSource会把Last-Event-ID属性作为请求头发送给服务器,这样服务器就可以根据这个Last-Event-ID作出相应的处理。这里需要注意⚠️的是,id字段不是必须的,服务器有可能不会在消息中带上id字段,这样子客户端就不会存在Last-Event-ID这个属性。所以为了保证数据可靠,我们需要在每条消息上带上id字段。
  • SSE不支持IE浏览器

使用示例

服务端:

const http = require('http');
const fs = require('fs');http.createServer((req, res) => {let data = fs.readFileSync('./1.json');// 服务器声明接下来发送的是事件流res.writeHead(200, {'Content-Type': 'text/event-stream','Cache-Control': 'no-cache','Connection': 'keep-alive','Access-Control-Allow-Origin': '*',});// 发送消息setInterval(() => {res.write('event: slide1\n'); // 事件类型res.write(`id: ${+new Date()}\n`); // 消息 IDres.write(`data:${data} \n`); // 消息数据res.write('retry: 10000\n'); // 重连时间res.write('\n\n'); // 消息结束}, 5000);
}).listen(2000);

客户端:

 if (window.EventSource) {// 创建 EventSource 对象连接服务器const source = new EventSource('http://localhost:2000');// 连接成功后会触发 open 事件source.addEventListener('open', () => {console.log('Connected');}, false);// 服务器发送信息到客户端时,如果没有 event 字段,默认会触发 message 事件source.addEventListener('message', e => {console.log(`message: ${e.data}`);}, false);// 自定义 EventHandler,在收到 event 字段为 slide 的消息时触发source.addEventListener('slide1', e => {console.log(`slide1: ${e.data}`); // => data: 7}, false);// 连接异常时会触发 error 事件并自动重连source.addEventListener('error', e => {if (e.target.readyState === EventSource.CLOSED) {console.log('Disconnected');} else if (e.target.readyState === EventSource.CONNECTING) {console.log('Connecting...');}}, false);} else {console.error('Your browser doesn\'t support SSE');} }

为了减少服务器的开销,我们也可以有目的的断开和重连简单的办法是服务器发送一个 关闭消息并指定一个重连的时间戳,客户端在触发关闭事件时关闭当前连接并创建 一个计时器,在重连时把计时器销毁。

二、轮询

客户端定时向服务器发送请求,如果服务端有数据就返回,没有则返回空数据

优点:实现简单
缺点:轮询时间确定,间隔太长时效性差,间隔太短,会造成大量无效的请求

三、WebSocket

什么是Socket?什么是WebSocket?

socket并不是一个新的协议,它只是为了便于程序员进行网络编程而对tcp/ip协议族通信机制的一种封装。

websocket协议是html5规范中的一部分。为客户端和服务端提供了一种全双工通信机制。他是一种全新的应用层协议。通常表示为ws://echo.websocket.org/?encoding=text,可以看出除了协议名和http不同之外,他的表示和传传统的url一致。

那么他是如何建立连接?如何进行数据交换?如何维持连接呢?

  • 如何建立连接

Websocket使用服用了HTTP的握手通道。具体指的是,客户端通过http请求与WebSocket服务端协商升级协议。协议升级完成后,和后续的数据交换遵照Websocket协议。那么客户端时如何进行协议升级呢?

WebSocket建立连接的过程

  • 数据交换

websocket客户端与服务端一旦建立连接,后续的操作都是基于数据帧传递

  • 维持连接

WebSocket为了保持客户端、服务端的实时双向通信,需要确保客户端、服务端之间的TCP道保持连接没有断开。然而,对于长时间没有数据往来的连接,如果依旧长时间保持着,可能会浪费包括的连接资源。但不排除有些场景,客户端、服务端虽然长时间没有数据往来,但仍需要保持连接。

这个时候,可以采用心跳来实现:

发送方->接收方:ping

接收方->发送方:pong
ping、pong的操作,对应的是WebSocket的两个控制帧,opcode分别是0x9、0xA

例如:WebSocket服务端向客户端发送ping,只需要如下代码(采用ws模块)ws.ping('', false, true);

SSE:使用HTTP做服务端数据推送的技术及其他通信技术相关推荐

  1. flux服务器推消息,服务端主动推送数据,除了 WebSocket 你还能想到啥?

    原标题:服务端主动推送数据,除了 WebSocket 你还能想到啥? 来自公众号: 江南一点雨 在 上篇文章 中,松哥和大家分享了 WebFlux 的基本用法,小伙伴们已经了解到使用 WebFlux ...

  2. 关于云开发新服务“实时数据推送”,你需要了解的全在这了!

    "微信小程序工程师邓坤力带你了解如何利用千呼万唤始出来的云开发实时数据推送服务打造生动的小程序和小游戏!" 在数据库在小程序·云开发中的应用一文中,我们了解到实时数据推送作为云开发 ...

  3. 服务端如何推送消息给客户端?

    大家好,我是前端西瓜哥,今天带大家了解一下服务端如何推送消息给客户端. 有时候,我们希望服务端能够主动推送一些信息给客户端.但 HTTP 协议只能让客户端发起请求然后服务端响应,而无法让服务端主动去发 ...

  4. pushlet实现单机-集群服务端消息推送

    一.什么是pushlet? 1.pushlet推送是一种将java后台数据推送到web页面的框架技术,实现了comet. 2.comet是一个用于描述客户端和服务器之间交互的术语,即使用长期保持的ht ...

  5. Asp.net SignalR 实现服务端消息推送到Web端

    参考博客https://www.cnblogs.com/wintersun/p/4148223.html ASP .NET SignalR是一个ASP .NET 下的类库,可以在ASP .NET 的W ...

  6. 使用SignalR从服务端主动推送警报日志到各种终端(桌面、移动、网页)

    工作上有个业务,.Net Core WebAPI作为服务端,需要将运行过程中产生的日志分类,并实时推送到各种终端进行报警,终端有桌面(WPF).移动(Xamarin.Forms).网站(Angular ...

  7. SSE 服务端消息推送

    SSE(Server-sent events) SSE 它是基于 HTTP 协议的,一般意义上的 HTTP 协议是无法做到服务端主动向客户端推送消息的.有一种变通方法,就是服务器向客户端声明,发送的是 ...

  8. 服务端主动推送数据,除了 WebSocket 你还能想到啥?

    在上篇文章中,松哥和大家分享了 WebFlux 的基本用法,小伙伴们已经了解到使用 WebFlux 我们的返回值可以是 Mono 也可以是 Flux,如果是 Flux,由于 Flux 中包含多个元素, ...

  9. 利用mochiweb让服务端主动推送数据至前端页面

    对于智能化监控软件,从wincc等国外的有相当积累的系统,以及国内一些小型的智能化集成软件,通常其监控数据通过前端绑定控件的方式,做到了实时的通讯,通过控件直接和后端服务交互.这种方式可以灵活的组态, ...

最新文章

  1. envi5.2中文版
  2. 我国将于今年春季发射空间站核心舱 空间站进入全面实施阶段
  3. mysql在linux下的安装_mysql在linux下的安装
  4. excel python插件_利用 Python 插件 xlwings 读写 Excel
  5. vs使用ado连接oracle,在VS环境下以ADO方式操作Oracle数据库
  6. php cbd架构,CBD模式
  7. sql按年、月、日、查询排序
  8. 存储过程和存储函数的区别
  9. 亲测有效,使用postman进行并发测试
  10. WRF学习笔记二:WRF-chem简单入门运行指南
  11. 图片如何在线生成GIF动画?轻松三步在线制作GIF动画
  12. 最全的web前端自学教程视频,免费分享
  13. input。file清除。js,jquery
  14. Windows Server 2003 64位操作系统安装sqlserver2000企业版
  15. 如何在以太坊网络上发布自己的代币
  16. [P4V]Perforce(P4V)使用教程
  17. 【java使用ffmpeg进行视频压缩】
  18. Qt 项目:windows计算器
  19. 微信小程序开店怎么做?
  20. kaldi 1d-CNN网络结构

热门文章

  1. 焊接自己打板的心形LED出现的问题
  2. 【C语言】数据类型(基本类型、构造类型、类型转换)
  3. 怎么将太大的word文档压缩变小,3个高效方法
  4. linux expect中文,Linux expect用法介绍
  5. goldengate mysql_Goldengate异构 mysql——oracl
  6. Elasticsearch报错: received plaintext http traffic on an https channel, closing connection ...
  7. 如何去写好公众号文章开头和结尾呢?
  8. Flutter学习-单子布局Widget
  9. java的webdriver_WebDriver之java篇
  10. 锂电池-hppc实验理解