请选择 进入手机版 | 继续访问电脑版
设为首页收藏本站

亿仁网

 找回密码
 立即注册

扫一扫,访问微社区

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 4110|回复: 0

WEB 实时推送技术的总结

[复制链接]
  • TA的每日心情
    奋斗
    2019-3-14 22:24
  • 签到天数: 160 天

    [LV.7]常住居民III

    1074

    主题

    1139

    帖子

    1万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    18046
     楼主| 发表于 2019-11-16 23:10:15 | 显示全部楼层 |阅读模式

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

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

    1.轮询(polling)

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

    • 优点:实现简单,无需做过多的更改
    • 缺点:轮询的间隔过长,会导致用户不能及时接收到更新的数据;轮询的间隔过短,会导致查询请求过多,增加服务器端的负担。
    1. <div id="clock"></div>
    2. <script>
    3.     let clockDiv = document.getElementById('clock');
    4.     setInterval(function(){
    5.         let xhr = new XMLHttpRequest;
    6.         xhr.open('GET','/clock',true);
    7.         xhr.onreadystatechange = function(){
    8.             if(xhr.readyState == 4 && xhr.status == 200){
    9.                 console.log(xhr.responseText);
    10.                 clockDiv.innerHTML = xhr.responseText;
    11.             }
    12.         }
    13.         xhr.send();
    14.     },1000);
    15. </script>
    复制代码
    1. //轮询  服务端
    2. let express = require('express');
    3. let app = express();
    4. app.use(express.static(__dirname));
    5. app.get('/clock',function(req,res){
    6.   res.end(new Date().toLocaleString());
    7. });
    8. app.listen(8080);
    复制代码

    2.长轮询(long-polling)

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

    优点:比 Polling 做了优化,有较好的时效性

    缺点:保持连接会消耗资源; 服务器没有返回有效数据,程序超时。

    1. <div id="clock"></div>
    2. <script>
    3. let clockDiv = document.getElementById('clock')
    4. function send() {
    5.   let xhr = new XMLHttpRequest()
    6.   xhr.open('GET', '/clock', true)
    7.   xhr.timeout = 2000 // 超时时间,单位是毫秒
    8.   xhr.onreadystatechange = function() {
    9.     if (xhr.readyState == 4) {
    10.       if (xhr.status == 200) {
    11.         //如果返回成功了,则显示结果
    12.         clockDiv.innerHTML = xhr.responseText
    13.       }
    14.       send() //不管成功还是失败都会发下一次请求
    15.     }
    16.   }
    17.   xhr.ontimeout = function() {
    18.     send()
    19.   }
    20.   xhr.send()
    21. }
    22. send()
    23. </script>
    复制代码

    3.iframe流(streaming)

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

    优点:消息能够实时到达;浏览器兼容好

    缺点:服务器维护一个长连接会增加开销;IE、chrome、Firefox会显示加载没有完成,图标会不停旋转。

    1. <body>
    2.     <div id="clock"></div>
    3.     <iframe src="/clock" style="display:none"></iframe>
    4. </body>
    5. //iframe流
    6. let express = require('express')
    7. let app = express()
    8. app.use(express.static(__dirname))
    9. app.get('/clock', function(req, res) {
    10.   setInterval(function() {
    11.     let date = new Date().toLocaleString()
    12.     res.write(`
    13.        <script type="text/javascript">
    14.          parent.document.getElementById('clock').innerHTML = "${date}";//改变父窗口dom元素
    15.        </script>
    16.      `)
    17.   }, 1000)
    18. })
    19. app.listen(8080)
    复制代码

    客户端只请求一次,然而服务端却是源源不断向客户端发送数据,这样服务器维护一个长连接会增加开销。
    以上我们介绍了三种实时推送技术,然而各自的缺点很明显,使用起来并不理想,接下来我们着重介绍另一种技术--websocket,它是比较理想的双向通信技术。



    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    造物之前,必先造人。
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|小黑屋|亿仁网 ( 粤ICP备16098737  

    GMT+8, 2020-8-12 05:10 , Processed in 0.765381 second(s), 27 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表