前言
随着 Web 的发展,用户对于 Web 的实时推送要求也越来越高 ,比如,工业运行监控、Web 在线通讯、即时报价系统、在线游戏等,都需要将后台发生的变化主动地、实时地传送到浏览器端,而不需要用户手动地刷新页面。本文对过去和现在流行的 Web 实时推送技术进行了比较与总结。
一、双向通信
HTTP 协议有一个缺陷:通信只能由客户端发起。举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。在WebSocket协议之前,有三种实现双向通信的方式:轮询(polling)、长轮询(long-polling)和iframe流(streaming)。
1.轮询(polling)
轮询是客户端和服务器之间会一直进行连接,每隔一段时间就询问一次。其缺点也很明显:连接数会很多,一个接受,一个发送。而且每次发送请求都会有Http的Header,会很耗流量,也会消耗CPU的利用率。
- 优点:实现简单,无需做过多的更改
- 缺点:轮询的间隔过长,会导致用户不能及时接收到更新的数据;轮询的间隔过短,会导致查询请求过多,增加服务器端的负担
- // 1.html
-
- <div id="clock"></div>
-
- <script>
-
- let clockDiv = document.getElementById('clock');
-
- setInterval(function(){
-
- let xhr = new XMLHttpRequest;
-
- xhr.open('GET','/clock',true);
-
- xhr.onreadystatechange = function(){
-
- if(xhr.readyState == 4 && xhr.status == 200){
-
- console.log(xhr.responseText);
-
- clockDiv.innerHTML = xhr.responseText;
-
- }
-
- }
-
- xhr.send();
-
- },1000);
-
- </script>
-
- //轮询 服务端
-
- let express = require('express');
-
- let app = express();
-
- app.use(express.static(__dirname));
-
- app.get('/clock',function(req,res){
-
- res.end(new Date().toLocaleString());
-
- });
-
- app.listen(8080);
启动本地服务,打开http://localhost:8080/1.html,得到如下结果:
2.长轮询(long-polling)
长轮询是对轮询的改进版,客户端发送HTTP给服务器之后,看有没有新消息,如果没有新消息,就一直等待。当有新消息的时候,才会返回给客户端。在某种程度上减小了网络带宽和CPU利用率等问题。由于http数据包的头部数据量往往很大(通常有400多个字节),但是真正被服务器需要的数据却很少(有时只有10个字节左右),这样的数据包在网络上周期性的传输,难免对网络带宽是一种浪费。
- 优点:比 Polling 做了优化,有较好的时效性
- 缺点:保持连接会消耗资源; 服务器没有返回有效数据,程序超时。
- // 2.html 服务端代码同上
-
- <div id="clock"></div>
-
- <script>
-
- let clockDiv = document.getElementById('clock')
-
- function send() {
-
- let xhr = new XMLHttpRequest()
-
- xhr.open('GET', '/clock', true)
-
- xhr.timeout = 2000 // 超时时间,单位是毫秒
-
- xhr.onreadystatechange = function() {
-
- if (xhr.readyState == 4) {
-
- if (xhr.status == 200) {
-
- //如果返回成功了,则显示结果
-
- clockDiv.innerHTML = xhr.responseText
-
- }
-
- send() //不管成功还是失败都会发下一次请求
-
- }
-
- }
-
- xhr.ontimeout = function() {
-
- send()
-
- }
-
- xhr.send()
-
- }
-
- send()
-
- </script>
3.iframe流(streaming)
(编辑:ASP站长网)
|