web通讯的四种方式,短轮询、长轮询(comet)、长连接(SSE)、WebSocket
一 短轮询
1.1 定义
http端轮询是服务器收到请求不管是否有数据都直接响应 http 请求;
其实就是普通的轮询。指在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给客户端的浏览器。
1.2 应用场景
传统的web通信模式。后台处理数据,需要一定时间,前端想要知道后端的处理结果,就要不定时的向后端发出请求以获得最新情况。
1.3 优点
前后端程序编写比较容易。
1.4 缺点
- 请求中有大半是无用,难于维护,浪费带宽和服务器资源;
- 响应的结果没有顺序(因为是异步请求,当发送的请求没有返回结果的时候,后面的请求又被发送。而此时如果后面的请求比前面的请 求要先返回结果,那么当前面的请求返回结果数据时已经是过时无效的数据了)。
1.5 实例:适于小型应用。
1.6 前端实现:
var xhr = new XMLHttpRequest();
setInterval(function(){
xhr.open('GET','/user');
xhr.onreadystatechange = function(){
};
xhr.send();
},1000)
二 长轮询
2.1 定义
客户端向服务器发送Ajax请求,服务器接到请求后hold住连接
,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。
2.2 优点
在无消息的情况下不会频繁的请求,耗费资源小。
2.3 缺点
- 服务器hold连接会消耗资源
- 返回数据顺序无保证,难于管理维护。
- 浏览器端对统一服务器同时 http 连接有最大限制, 最好同一用户只存在一个长轮询;
2.4 实例:WebQQ、Hi网页版、Facebook IM。
2.5 前端实现:
function ajax(){
var xhr = new XMLHttpRequest();
xhr.open('GET','/user');
xhr.onreadystatechange = function(){
ajax();
};
xhr.send();
}
长轮训和短轮训
相同点:
- 可以看出 http 长轮询和 http 短轮询的都会 hold 一段时间;
不同点
- 间隔发生在服务端还是浏览器端: http 长轮询在服务端会 hold 一段时间, http 短轮询在浏览器端 “hold”一段时间;
三 http 长连接
目前 http 协议普遍使用的是 1.1 版本, 之前有个 1.0 版本,两者之间的一个区别是 1.1 支持 http 长连接, 或者叫持久连接。
1.0 不支持 http 长连接, 每次一个 http请求响应后都关闭 tcp 连接, 下个 http 请求会重新建立 tcp 连接.
3.1定义
多个 http 请求共用一个 tcp 连接; 这样可以减少多次临近 http 请求导致 tcp建立关闭所产生的时间消耗.
http 1.1 中在请求头和相应头中用 connection
字段标识是否是 http长连接, connection: keep-alive, 表明是 http 长连接; connection:closed, 表明服务器关闭 tcp 连接
与 connection 对应的一个字段是 keep-live
, http 响应头中出现, 他的格式是 timeout=30,max=5
, timeout 是两次 http 请求保持的时间(s), , max 是这个 tcp 连接最多为几个 http请求重用
3.2优点
消息即时到达,不发无用请求;管理起来也相对方便。
3.3 缺点
服务器维护一个长连接会增加开销。
3.4实例:Gmail聊天
四 Web Socket
4.1定义
Websocket是基于HTTP协
议的,在和服务端建立了链接后,服务端有数据有了变化后会主动推送给前端。
4.2优点
请求响应快,不浪费资源。(传统的http请求,其并发能力都是依赖同时发起多个TCP连接访问服务器实现的(因此并发数受限于浏览器允许的并发连接数),而websocket则允许我们在一条ws连接上同时并发多个请求,即在A请求发出后A响应还未到达,就可以继续发出B请求。由于TCP的慢启动特性(新连接速度上来是需要时间的),以及连接本身的握手损耗,都使得websocket协议的这一特性有很大的效率提升;http协议的头部太大,且每个请求携带的几百上千字节的头部大部分是重复的,websocket则因为复用长连接而没有这一问题。)
4.3缺点:
- 主流浏览器支持的Web Socket版本不一致;
- 服务端没有标准的API。
4.4实例:实现即时通讯:如股票交易行情分析、聊天室、在线游戏等,替代轮询和长轮询
4.5 解决:解决了http协议的两个问题。
- 1.服务端的被动性。http协议是只有客户端询问之后才回复。解决了同步有延迟的问题
- 2.解决了服务器上消耗资源的问题
4.6 实现:
//需要先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>
4.7 WebSocket四个事件操作
- onmessage收到服务器响应时执行
- onerroe 出现异常时执行
- onopen 建立起连接时执行
- onclose 断开连接时执行