# 简介

轮询、长连接和 WebSocket 都是实现 Web 即时通信的机制。根据基于的协议可以分为两类:基于 HTTP 协议实现和基于 WebSocket 协议实现。
这里主要介绍基于 HTTP 协议的三种方式:短轮询、长轮询和长连接。

# 短轮询

| 定义

短轮询就是普通的、常规的轮询:浏览器每隔一段固定的时间就像服务器发送 HTTP 请求,服务器在收到请求后,不管是否有数据需要发送更新,都直接进行响应。

本质上还是浏览器发送请求,服务器接收请求的过程

| 实现

  1. var xhr = new XMLHttpRequest();
  2. setInterval(function(){
  3. xhr.open('GET','/user');
  4. xhr.onreadystatechange = function(){};
  5. xhr.send();
  6. },1000)

| 特点

  • 实现简单;
  • 因为需要不断的建立新的 HTTP 连接,非常浪费服务器和客户端的资源;
  • 响应的结果没有顺序并且包含一定的延时;

    # 长轮询:comet

    | 流程

  • 客户端发送 Ajax 请求到服务器,服务器在有消息之前将该请求挂起。

  • 当服务端数据更新或者有消息后,服务器将作出响应。如果一直没有数据更新,则到达一定的时间限制也会做出响应。
  • 客户端处理服务器的响应后,立即发出一个新的请求。

image.png

| 实现

  1. function ajax(){
  2. var xhr = new XMLHttpRequest();
  3. xhr.open('GET','/user');
  4. xhr.onreadystatechange = function(){
  5. ajax();
  6. };
  7. xhr.send();
  8. }

| 特点

* 优点

  • 和短轮询相比数据未更新时不会频繁的请求,耗费的资源少。

    * 缺点

  • 服务器挂起连接会消耗服务器的资源;

  • 响应数据没有顺序;
  • 在同一时刻,客户端对相同服务器的 HTTP 连接数量有最大限制。最好同一个用户只存在一个长轮询。

    # 长连接:SSE

    | 定义

    长连接是 HTTP/1.1 中出现的。它本质上和轮询机制不同,允许多个 HTTP 请求共用一个TCP 连接。服务器只要数据有更新就可以马上发送到客户端。

    SSE:Server-Sent Events 可以减少频繁建立 TCP 连接所带来的资源浪费和时间损耗。

| 实现

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script type="text/javascript">
  7. //需要判断浏览器支不支持,可以去w3c进行查看
  8. var source = new EventSource('/get_data');
  9. source.onmessage = function (event) {
  10. console.info(event.data);
  11. document.getElementById('result').innerText = event.data
  12. };
  13. </script>
  14. </head>
  15. <body>
  16. <div id="result"></div>
  17. </body>
  18. </html>
  1. //produces必须为"text/event-stream;charset=UTF-8"
  2. @RequestMapping(value = "/get_data", produces = "text/event-stream;charset=UTF-8")
  3. public String getData(){
  4. try {
  5. Thread.sleep(1000);
  6. }catch (Exception e) {
  7. e.printStackTrace();
  8. }
  9. double moeny=Math.random()*10;
  10. System.out.println(String.format("%.2f",moeny));
  11. DecimalFormat df = new DecimalFormat(".00");
  12. String canshu=df.format(moeny);
  13. //EventSource返回的参数必须以data:开头,"\n\n"结尾,不然onmessage方法无法执行。
  14. return "data:白菜价格行情:" + canshu+"元"+ "\n\n";
  15. }

| 特点

* 优点

  • 多个 HTTP 请求共用一个 TCP 连接,不需要建立或保持大量的请求。

    * 缺点

  • 服务器维护一个长连接会增加开销。

  • 浏览器对同一个域有并发数量限制,长连接会持续性的占用浏览器和服务器的一个连接,从而资源无法释放。

    例:Chrome 浏览器对于并发数量的限制为6

| 对比 WebSocket 协议

  • SSE 使用 HTTP 协议,现有的服务器软件都支持。WebSocket 是一个独立协议。
  • SSE 通常只用来传送文本,二进制数据需要编码后传送。WebSocket 默认支持传送二进制数据。
  • SSE 属于轻量级,使用简单。WebSocket 协议相对复杂。
  • SSE 默认支持断线重连。WebSocket 需要自己实现。
  • SSE 支持自定义发送的消息类型。
  • SSE是 单通道,WebSocket 是双通道。

    单通道:使用 SSE 时,服务端向客户端发消息且占用一个连接。如果客户端要向服务端通信,需额外打开一个连接。

# 参考

  1. 长轮询(Long polling)
  2. 轮询、长轮询、长连接、websocket
  3. web通讯的四种方式,短轮询、长轮询(comet)、长连接(SSE)、WebSocket
  4. springboot的服务端推送技术SSE
  5. 轮询、长轮询(comet)、长连接(SSE)、WebSocket—简书