这要介绍三种数据推送方式:
1. Comet:基于Http长连接的服务器推送技术
2.基于WebSocket推送方案
3.SSE(Server-Send Event):服务器推送数据新方式
Comet:基于Http长连接的服务器推送技术
这是一种最原始也是最好用的数据推送技术,服务器不释放不停的往客户端输送资源。
Comet:基于 HTTP 长连接的服务器推送技术,Comet 是一种 Web 应用架构。服务器端会主动以异步的方式向客户端程序推送数据,而不需要客户端显式的发出请求。Comet 架构非常适合事件驱动的 Web 应用,以及对交互性和实时性要求很强的应用。
首先建立php来看php如何不释放输送资源,创建一个data.php文件:
1 2 3 4 5 6 7 8 9 10 11 |
<?php header("Cache-Control:max-age=0"); $i = 0; while(true){ $i++; $radom= rand(1,999); echo $radom; ob_flush(); flush(); } ?> |
你会发现页面只会一次输出,不能连续输出。这个时候我们调整代码,添加一个sleep()函数让他睡一会儿:
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php header("Cache-Control:max-age=0"); $i = 0; while(true){ $i++; sleep(1); $radom= rand(1,999); echo $radom."<br />"; ob_flush(); flush(); } ?> |
(注意此方法在apache环境中有效,其他环境可能会整体输出,并无缓冲输出效果)
这种效果就达到了,效果,但是我们只是在后端执行。
下面我们将介绍如何让前端和后端结合来实现这样的效果:
我们先写一个ajax来调用刚才的页面,创建index.html文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<meta charset="utf-8" /> <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.11/jquery.min.js"></script> <h1>测试</h1> <script type="text/javascript" > $.ajax({ url:'data.php' dataType:"json", success:function(data){ console.log(data); } }); </script> |
你会发现,这个请求一直在继续。
无法立刻输出页面,这是因为php端一直执行并未执行完。jquery的ajax会一直等待后台执行完毕才会输出。那如何处理呢。
首先我们修改服务器端php代码:
1 2 3 4 5 6 7 8 |
<?php header("Content-type:appliacation/json;charset=utf-8"); header("Cache-Control:max-age=0"); sleep(1); $radom= rand(1,999); echo $radom; ?> |
前端代码更改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<meta charset="utf-8" /> <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.11/jquery.min.js"></script> <h1>测试</h1> <script type="text/javascript" > function conn(){ $.ajax({ url:'data.php' dataType:"json", success:function(data){ console.log(data); conn(); } }); } conn(); </script> |
你会发现前端我们做了一个死循环,来不断调用后端方法。
当然你也可以这样来做服务器端代码php改写成这样也可(php为死循环时想让前端输出需要加入exit函数):
1 2 3 4 5 6 7 8 9 10 11 |
<?php header("Content-type:appliacation/json;charset=utf-8"); header("Cache-Control:max-age=0"); sleep(1); while(true){ $radom= rand(1,999); echo $radom; exit(); } ?> |
这样折腾一圈其实没啥用。
我们用ajax循环请求服务器端数据,也就说服务器是死的,js调用。网络请求特别昂贵。下面来了解更加高级的websocket技术
基于WebSocket推送方案
基于WebSocket 的推送方案,在浏览器中通过http仅能实现单向的通信,comet可以一定程度上模拟双向通信,但效率较低,并需要服务器有较好的支持; flash中的socket和xmlsocket可以实现真正的双向通信,通过 flex ajax bridge,可以在javascript中使用这两项功能. 可以预见,如果websocket一旦在浏览器中得到实现,将会替代上面两项技术,得到广泛的使用.面对这种状况,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽并达到实时通讯。如聊天室等。
下面就来了解一下前端浏览器的websocket和node.js之间的交互,首先你不必须安装socket.io.
让我们来新建一个index.html文件,此文件放入node项目目录的views文件夹中:
1 2 3 4 5 6 7 8 9 10 11 12 |
<!doctype html> <html> <head> <meta charset="utf-8" > <title>websocket demo</title> </head> <body> <script src="javascripts/jquery.js" ></script> <script src="javascripts/socket.io.js"></script> <script src="javascripts/main.js"></script> </body> </html> |
下面在我们的main.js里我们做一些简单的调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$(funciton(){ var i = 0; //建立websocket连接 socket = io.connect('http://localhost:3000'); //收到server的连接确认 socket.on('open',function(){ console.log('已连接'); //给服务器发消息 socket.send('连接成功'); }) //监听message事件,打印消息信息 socket.on('test',function(json){ console.log('test',json); }) }) |
下面我们来看看node的app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
..... app=express(), io= require('socket.io').listen(server); //websocket连接监听 io.on('connection',function(socket){ socket.emit('open');//通知客户端已连接open,客户端open就会被触发 //打印握手信息 // console.log(socket.handshake); //对message事件的监听 socket.on('message',function(msg){ console.log('服务器接收到客户端的消息',msg); //返回消息(可以省略) socket.emit('test','server ready'); //广播向所有用户发消息 //socket.broadcast.emit(''); }); //监听退出事件 socket.on('disconnect',function(){}); }) //指定websocket的客户端的html文件 app.get('/',function(req,res){ res.sendfile('views/index.html'); }); server.listen(app.get('post'),function(){ console.log("socket server listening on port"+ app.get('post')); }); |
SSE(Server-Send Event):服务器推送数据新方式
服务器推送数据的新方式SSE,传统的网页都是浏览器向服务器”查询”数据,但是很多场合,最有效的方式是服务器向浏览器”发送”数据。比如,每当收到新的电子邮件,服务器就向浏览器发送一个”通知”,这要比浏览器按时向服务器查询(polling)更有效率。服务器发送事件(Server-Sent Events,简称SSE)就是为了解决这个问题,而提出的一种新API,部署在EventSource对象上。目前,除了IE,其他主流浏览器都支持。
例如,股票和实时推送数据很需要他。
首先建立php文件:
1 2 3 4 5 6 7 8 |
// data.php <?php header("Content-Type:text/event-stream;charset=utf-8");//utf8编码 header("Access-Control-Allow-Origin:http://127.0.0.1/");//指定127.0.0.1这个域可以访问 //以下是数据格式 echo "data:现在北京时间是11\r\n\r\n"; |
建立html文件
1 2 3 4 5 6 |
// index.html <meta charset="utf-8" /> <div id="text"></div> <script type="text/javascript" src="index.js"></script> |
下面来看看主要方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
//index.js var source; function init(){ //访问服务器页面 source = new EventSource('http://localhost/sse/data.php'); //open是和服务器建立连接。this.readyState=1 为连接成功 //当成功与服务器建立连接时产生 source.onopen = function(){ console.log("连接已经建立",this.readyState); } //回调,获取从服务器获取的数据 //当收到服务器发送的事件时产生 source.onmessage = function(evnet){ document.getElementById('text').innerHTML += "--"+evnet.data+"<br/>"; console.log("从服务器获取数据",evnet.data); } //当出现错误时产生 source.onerror = function(){ } } init(); |
EventSource访问服务器获得服务器源, EventSource提供事件的说明
表 . EventSource 对象提供的标准事件
名称 | 说明 | 事件处理方法 |
---|---|---|
open | 当成功与服务器建立连接时产生 | onopen |
message | 当收到服务器发送的事件时产生 | onmessage |
error | 当出现错误时产生 | onerror |
前段时间研究了一下goeasy,代码简洁易读,服务稳定。后台推送只需要两行代码, js前端推送也只需要3,4行,而且文档齐全,还提供了后台查询信息收发情况,所以我觉得GoEasy推送服务是个不错的选择。官网: https://goeasy.io/