今天看到了短轮询和长轮询这两个名词,于是我就查了一下是什么意思。
Polling<轮询>:不管服务端数据有无更新,客户端每隔定长时间请求拉取一次数据,可能有更新数据返回,也可能什么都没有。
Long Polling<长轮询>:客户端发起Long Polling,此时如果服务端没有相关数据,会hold住请求,直到服务端有相关数据,或者等待一定时间超时才会返回。返回后,客户端又会立即再次发起下一次Long
Polling。(所谓的hold住请求指的服务端暂时不回复结果,保存相关请求,不关闭请求连接,等相关数据准备好,写会客户端。)
短轮询
定义:其实就是普通的轮询。指在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给客户端的浏览器。
应用场景:传统的web通信模式。后台处理数据,需要一定时间,前端想要知道后端的处理结果,就要不定时的向后端发出请求以获得最新情况。
优点:前后端程序编写比较容易。
缺点:请求中有大半是无用,难于维护,浪费带宽和服务器资源;响应的结果没有顺序(因为是异步请求,当发送的请求没有返回结果的时候,后面的请求又被发送。而此时如果后面的请求比前面的请 求要先返回结果,那么当前面的请求返回结果数据时已经是过时无效的数据了)。
实例:适于小型应用。
前端实现:
var xhr = new XMLHttpRequest();
setInterval(function(){
xhr.open('GET','/user');
xhr.onreadystatechange = function(){
ajax()
};
xhr.send();
},1000)
长轮询
定义:客户端向服务器发送Ajax请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。
优点:在无消息的情况下不会频繁的请求,耗费资源小。
缺点:服务器hold连接会消耗资源,返回数据顺序无保证,难于管理维护。
实例:WebQQ、Hi网页版、Facebook IM。
前端实现:
function ajax(){
var xhr = new XMLHttpRequest();
xhr.open('GET','/user');
xhr.onreadystatechange = function(){
ajax();
};
xhr.send();
}
Web Socket
定义:Websocket是基于HTTP协议的,在和服务端建立了链接后,服务端有数据有了变化后会主动推送给前端。
优点:请求响应快,不浪费资源。(传统的http请求,其并发能力都是依赖同时发起多个TCP连接访问服务器实现的(因此并发数受限于浏览器允许的并发连接数),而websocket则允许我们在一条ws连接上同时并发多个请求,即在A请求发出后A响应还未到达,就可以继续发出B请求。由于TCP的慢启动特性(新连接速度上来是需要时间的),以及连接本身的握手损耗,都使得websocket协议的这一特性有很大的效率提升;http协议的头部太大,且每个请求携带的几百上千字节的头部大部分是重复的,websocket则因为复用长连接而没有这一问题。)
缺点:主流浏览器支持的Web Socket版本不一致;服务端没有标准的API。
实例:实现即时通讯:如股票交易行情分析、聊天室、在线游戏等,替代轮询和长轮询
解决:解决了http协议的两个问题。
1.服务端的被动性。http协议是只有客户端询问之后才回复。解决了同步有延迟的问题
2.解决了服务器上消耗资源的问题
实现:
//需要先npm install ws
//服务器端
var Server = require('ws').Server;
var wss = new Server({
port:2000
});
wss.on('connection',function(ws){
ws.on('message',function(data){
ws.send('你好,客户端,我是服务器!');
console.log(data);
})
});
//node客户端
var WebSocket = require('ws');
var socket = new WebSocket('ws://localhost:2000/');
socket.on('open',function(){
socket.send('你好,服务器,我是客户端');
});
socket.on('message',function(event){
console.log(event);
})
//html客户端(注:浏览器客户端与node客户端只需要一种)
<script>
var socket = new WebSocket('ws://localhost:2000/');
socket.onopen = function(){
};
socket.onmessage = function(event){
console.log(event.data)
}
</script>