# 简介
轮询、长连接和 WebSocket 都是实现 Web 即时通信的机制。根据基于的协议可以分为两类:基于 HTTP 协议实现和基于 WebSocket 协议实现。
这里主要介绍基于 HTTP 协议的三种方式:短轮询、长轮询和长连接。
# 短轮询
| 定义
短轮询就是普通的、常规的轮询:浏览器每隔一段固定的时间就像服务器发送 HTTP 请求,服务器在收到请求后,不管是否有数据需要发送更新,都直接进行响应。
本质上还是浏览器发送请求,服务器接收请求的过程
| 实现
var xhr = new XMLHttpRequest();setInterval(function(){xhr.open('GET','/user');xhr.onreadystatechange = function(){};xhr.send();},1000)
| 特点
- 实现简单;
- 因为需要不断的建立新的 HTTP 连接,非常浪费服务器和客户端的资源;
-
# 长轮询:comet
| 流程
客户端发送 Ajax 请求到服务器,服务器在有消息之前将该请求挂起。
- 当服务端数据更新或者有消息后,服务器将作出响应。如果一直没有数据更新,则到达一定的时间限制也会做出响应。
- 客户端处理服务器的响应后,立即发出一个新的请求。
| 实现
function ajax(){var xhr = new XMLHttpRequest();xhr.open('GET','/user');xhr.onreadystatechange = function(){ajax();};xhr.send();}
| 特点
* 优点
-
* 缺点
服务器挂起连接会消耗服务器的资源;
- 响应数据没有顺序;
- 在同一时刻,客户端对相同服务器的 HTTP 连接数量有最大限制。最好同一个用户只存在一个长轮询。
# 长连接:SSE
| 定义
长连接是 HTTP/1.1 中出现的。它本质上和轮询机制不同,允许多个 HTTP 请求共用一个TCP 连接。服务器只要数据有更新就可以马上发送到客户端。SSE:Server-Sent Events 可以减少频繁建立 TCP 连接所带来的资源浪费和时间损耗。
| 实现
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><script type="text/javascript">//需要判断浏览器支不支持,可以去w3c进行查看var source = new EventSource('/get_data');source.onmessage = function (event) {console.info(event.data);document.getElementById('result').innerText = event.data};</script></head><body><div id="result"></div></body></html>
//produces必须为"text/event-stream;charset=UTF-8"@RequestMapping(value = "/get_data", produces = "text/event-stream;charset=UTF-8")public String getData(){try {Thread.sleep(1000);}catch (Exception e) {e.printStackTrace();}double moeny=Math.random()*10;System.out.println(String.format("%.2f",moeny));DecimalFormat df = new DecimalFormat(".00");String canshu=df.format(moeny);//EventSource返回的参数必须以data:开头,"\n\n"结尾,不然onmessage方法无法执行。return "data:白菜价格行情:" + canshu+"元"+ "\n\n";}
| 特点
* 优点
多个 HTTP 请求共用一个 TCP 连接,不需要建立或保持大量的请求。
* 缺点
服务器维护一个长连接会增加开销。
- 浏览器对同一个域有并发数量限制,长连接会持续性的占用浏览器和服务器的一个连接,从而资源无法释放。
例:Chrome 浏览器对于并发数量的限制为6
| 对比 WebSocket 协议
- SSE 使用 HTTP 协议,现有的服务器软件都支持。WebSocket 是一个独立协议。
- SSE 通常只用来传送文本,二进制数据需要编码后传送。WebSocket 默认支持传送二进制数据。
- SSE 属于轻量级,使用简单。WebSocket 协议相对复杂。
- SSE 默认支持断线重连。WebSocket 需要自己实现。
- SSE 支持自定义发送的消息类型。
- SSE是 单通道,WebSocket 是双通道。
单通道:使用 SSE 时,服务端向客户端发消息且占用一个连接。如果客户端要向服务端通信,需额外打开一个连接。
