浅谈Web 实时推送技术,有对比,有总结

新闻 前端
随着 Web 的发展,用户对于 Web 的实时推送要求也越来越高。本文对过去和现在流行的 Web 实时推送技术进行了比较与总结。

前言

随着 Web 的发展,用户对于 Web 的实时推送要求也越来越高 ,比如,工业运行监控、Web 在线通讯、即时报价系统、在线游戏等,都需要将后台发生的变化主动地、实时地传送到浏览器端,而不需要用户手动地刷新页面。本文对过去和现在流行的 Web 实时推送技术进行了比较与总结。

一、双向通信

HTTP 协议有一个缺陷:通信只能由客户端发起。举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。在WebSocket协议之前,有三种实现双向通信的方式:轮询(polling)、长轮询(long-polling)和iframe流(streaming)

1.轮询(polling)

浅谈Web 实时推送技术,有对比,有总结

轮询是客户端和服务器之间会一直进行连接,每隔一段时间就询问一次。其缺点也很明显:连接数会很多,一个接受,一个发送。而且每次发送请求都会有Http的Header,会很耗流量,也会消耗CPU的利用率

  • 优点:实现简单,无需做过多的更改
  • 缺点:轮询的间隔过长,会导致用户不能及时接收到更新的数据;轮询的间隔过短,会导致查询请求过多,增加服务器端的负担
  1. // 1.html 
  2.  
  3. <div id="clock"></div> 
  4.  
  5. <script> 
  6.  
  7. let clockDiv = document.getElementById('clock'); 
  8.  
  9. setInterval(function(){ 
  10.  
  11. let xhr = new XMLHttpRequest; 
  12.  
  13. xhr.open('GET','/clock',true); 
  14.  
  15. xhr.onreadystatechange = function(){ 
  16.  
  17. if(xhr.readyState == 4 && xhr.status == 200){ 
  18.  
  19. console.log(xhr.responseText); 
  20.  
  21. clockDiv.innerHTML = xhr.responseText; 
  22.  
  23.  
  24.  
  25. xhr.send(); 
  26.  
  27. },1000); 
  28.  
  29. </script> 
  30.  
  31. //轮询 服务端 
  32.  
  33. let express = require('express'); 
  34.  
  35. let app = express(); 
  36.  
  37. app.use(express.static(__dirname)); 
  38.  
  39. app.get('/clock',function(req,res){ 
  40.  
  41. res.end(new Date().toLocaleString()); 
  42.  
  43. }); 
  44.  
  45. app.listen(8080); 

启动本地服务,打开http://localhost:8080/1.html,得到如下结果:

浅谈Web 实时推送技术,有对比,有总结

2.长轮询(long-polling)

浅谈Web 实时推送技术,有对比,有总结

长轮询是对轮询的改进版,客户端发送HTTP给服务器之后,看有没有新消息,如果没有新消息,就一直等待。当有新消息的时候,才会返回给客户端。在某种程度上减小了网络带宽和CPU利用率等问题。由于http数据包的头部数据量往往很大(通常有400多个字节),但是真正被服务器需要的数据却很少(有时只有10个字节左右),这样的数据包在网络上周期性的传输,难免对网络带宽是一种浪费

  • 优点:比 Polling 做了优化,有较好的时效性
  • 缺点:保持连接会消耗资源; 服务器没有返回有效数据,程序超时。
  1. // 2.html 服务端代码同上 
  2.  
  3. <div id="clock"></div> 
  4.  
  5. <script> 
  6.  
  7. let clockDiv = document.getElementById('clock'
  8.  
  9. function send() { 
  10.  
  11. let xhr = new XMLHttpRequest() 
  12.  
  13. xhr.open('GET''/clock'true
  14.  
  15. xhr.timeout = 2000 // 超时时间,单位是毫秒 
  16.  
  17. xhr.onreadystatechange = function() { 
  18.  
  19. if (xhr.readyState == 4) { 
  20.  
  21. if (xhr.status == 200) { 
  22.  
  23. //如果返回成功了,则显示结果 
  24.  
  25. clockDiv.innerHTML = xhr.responseText 
  26.  
  27.  
  28. send() //不管成功还是失败都会发下一次请求 
  29.  
  30.  
  31.  
  32. xhr.ontimeout = function() { 
  33.  
  34. send() 
  35.  
  36.  
  37. xhr.send() 
  38.  
  39.  
  40. send() 
  41.  
  42. </script> 

3.iframe流(streaming)

浅谈Web 实时推送技术,有对比,有总结

iframe流方式是在页面中插入一个隐藏的iframe,利用其src属性在服务器和客户端之间创建一条长连接,服务器向iframe传输数据(通常是HTML,内有负责插入信息的javascript),来实时更新页面。

  • 优点:消息能够实时到达;浏览器兼容好
  • 缺点:服务器维护一个长连接会增加开销;IE、chrome、Firefox会显示加载没有完成,图标会不停旋转。
  1. // 3.html 
  2.  
  3. <body> 
  4.  
  5. <div id="clock"></div> 
  6.  
  7. <iframe src="/clock" style="display:none"></iframe> 
  8.  
  9. </body> 
  10.  
  11. //iframe流 
  12.  
  13. let express = require('express'
  14.  
  15. let app = express() 
  16.  
  17. app.use(express.static(__dirname)) 
  18.  
  19. app.get('/clock'function(req, res) { 
  20.  
  21. setInterval(function() { 
  22.  
  23. let date = new Date().toLocaleString() 
  24.  
  25. res.write(` 
  26.  
  27. <script type="text/javascript"
  28.  
  29. parent.document.getElementById('clock').innerHTML = "${date}";//改变父窗口dom元素 
  30.  
  31. </script> 
  32.  
  33. `) 
  34.  
  35. }, 1000) 
  36.  
  37. }) 
  38.  
  39. app.listen(8080) 

启动本地服务,打开http://localhost:8080/3.html,得到如下结果:

浅谈Web 实时推送技术,有对比,有总结

上述代码中,客户端只请求一次,然而服务端却是源源不断向客户端发送数据,这样服务器维护一个长连接会增加开销。

以上我们介绍了三种实时推送技术,然而各自的缺点很明显,使用起来并不理想,接下来我们着重介绍另一种技术--websocket,它是比较理想的双向通信技术。

二、WebSocket

1.什么是websocket

WebSocket是一种全新的协议,随着HTML5草案的不断完善,越来越多的现代浏览器开始全面支持WebSocket技术了,它将TCP的Socket(套接字)应用在了webpage上,从而使通信双方建立起一个保持在活动状态连接通道。

一旦Web服务器与客户端之间建立起WebSocket协议的通信连接,之后所有的通信都依靠这个专用协议进行。通信过程中可互相发送JSON、XML、HTML或图片等任意格式的数据。由于是建立在HTTP基础上的协议,因此连接的发起方仍是客户端,而一旦确立WebSocket通信连接,不论服务器还是客户端,任意一方都可直接向对方发送报文

初次接触 WebSocket 的人,都会问同样的问题:我们已经有了 HTTP 协议,为什么还需要另一个协议?

2.HTTP的局限性

  • HTTP是半双工协议,也就是说,在同一时刻数据只能单向流动,客户端向服务器发送请求(单向的),然后服务器响应请求(单向的)。
  • 服务器不能主动推送数据给浏览器。这就会导致一些高级功能难以实现,诸如聊天室场景就没法实现。

3.WebSocket的特点

  • 支持双向通信,实时性更强
  • 可以发送文本,也可以发送二进制数据
  • 减少通信量:只要建立起WebSocket连接,就希望一直保持连接状态。和HTTP相比,不但每次连接时的总开销减少,而且由于WebSocket的首部信息很小,通信量也相应减少了
浅谈Web 实时推送技术,有对比,有总结
  •  

相对于传统的HTTP每次请求-应答都需要客户端与服务端建立连接的模式,WebSocket是类似Socket的TCP长连接的通讯模式,一旦WebSocket连接建立后,后续数据都以帧序列的形式传输。在客户端断开WebSocket连接或Server端断掉连接前,不需要客户端和服务端重新发起连接请求。在海量并发和客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息是在同一个持久连接上发起,实时性优势明显

接下来我看下websocket如何实现客户端与服务端双向通信:

  1. // websocket.html 
  2.  
  3. <div id="clock"></div> 
  4.  
  5. <script> 
  6.  
  7. let clockDiv = document.getElementById('clock'
  8.  
  9. let socket = new WebSocket('ws://localhost:9999'
  10.  
  11. //当连接成功之后就会执行回调函数 
  12.  
  13. socket.onopen = function() { 
  14.  
  15. console.log('客户端连接成功'
  16.  
  17. //再向服务 器发送一个消息 
  18.  
  19. socket.send('hello'//客户端发的消息内容 为hello 
  20.  
  21.  
  22. //绑定事件是用加属性的方式 
  23.  
  24. socket.onmessage = function(event) { 
  25.  
  26. clockDiv.innerHTML = event.data 
  27.  
  28. console.log('收到服务器端的响应', event.data) 
  29.  
  30.  
  31. </script> 
  32.  
  33. // websocket.js 
  34.  
  35. let express = require('express'
  36.  
  37. let app = express() 
  38.  
  39. app.use(express.static(__dirname)) 
  40.  
  41. //http服务器 
  42.  
  43. app.listen(3000) 
  44.  
  45. let WebSocketServer = require('ws').Server 
  46.  
  47. //用ws模块启动一个websocket服务器,监听了9999端口 
  48.  
  49. let wsServer = new WebSocketServer({ port: 9999 }) 
  50.  
  51. //监听客户端的连接请求 当客户端连接服务器的时候,就会触发connection事件 
  52.  
  53. //socket代表一个客户端,不是所有客户端共享的,而是每个客户端都有一个socket 
  54.  
  55. wsServer.on('connection'function(socket) { 
  56.  
  57. //每一个socket都有一个***的ID属性 
  58.  
  59. console.log(socket) 
  60.  
  61. console.log('客户端连接成功'
  62.  
  63. //监听对方发过来的消息 
  64.  
  65. socket.on('message'function(message) { 
  66.  
  67. console.log('接收到客户端的消息', message) 
  68.  
  69. socket.send('服务器回应:' + message) 
  70.  
  71. }) 
  72.  
  73. }) 

启动本地服务,打开http://localhost:3000/websocket.html,得到如下结果:

浅谈Web 实时推送技术,有对比,有总结

三、Web 实时推送技术的比较

浅谈Web 实时推送技术,有对比,有总结

综上所述:Websocket协议不仅解决了HTTP协议中服务端的被动性,即通信只能由客户端发起,也解决了数据同步有延迟的问题,同时还带来了明显的性能优势,所以websocket 是Web 实时推送技术的比较理想的方案,但如果要兼容低版本浏览器,可以考虑用轮询来实现。

责任编辑:张燕妮 来源: 头条科技
相关推荐

2022-07-30 10:08:06

MQTT​协议物联网

2018-11-07 09:15:04

主流Web服务器

2023-09-19 15:33:50

Web实时消息推送

2011-07-06 10:23:57

虚拟化服务器

2023-06-28 15:49:35

2022-09-13 10:23:52

MLOpsDevOps开发

2011-08-02 11:08:54

2015-03-10 15:32:46

LTE-ALTE

2021-01-22 11:42:58

比特币数字货币加密货币

2020-12-17 11:13:34

积木报表帆软报表开源1.0-beta

2022-01-28 11:34:39

区块链比特币技术

2022-03-13 23:15:58

区块链比特币加密货币

2022-01-27 11:34:02

区块链比特币技术

2014-03-17 16:38:27

京东

2020-09-16 15:24:33

监控安装

2023-01-04 10:45:23

5G

2017-06-06 10:30:12

前端Web宽度自适应

2009-09-27 09:41:21

Web开发

2021-12-08 10:19:06

Web开发数据

2022-12-06 15:59:14

人工智能
点赞
收藏

51CTO技术栈公众号