WebSocket的理解与使用

  1. 什么是WebSocket?php

    WebSocket是HTML5开始提供的一种在TCP链接上进行全双工通信的协议,是一种服务器推送技术html

  2. WebSocket出现以前客户端如何获取服务端的实时数据?html5

    Comet:是一种服务器向页面推送数据的技术。有如下实现方式:node

    (1) ajax轮询:浏览器定时向服务器发送请求,询问服务器是否有新信息。web

    (2) 长轮询:客户端发送请求后,服务器会保持链接,直到有新数据返回给客户端或请求超时。客户端收到数据并处理完,或者请求超时后,再向服务端发送新请求。ajax

    (3) HTTP流:浏览器向服务器发送一个请求,服务器保持链接打开,而后周期性地向浏览器发送数据。浏览器经过侦听readystatechange事件及检测readyState的值是否为3,是则比较此前接收到的数据,决定从收到的数据中的什么位置开始取得最新的数据。小程序

    (4) SSE:服务器发送事件,是围绕只读Comet交互推出的API。使用SSE API建立到服务器的单向链接,服务器能够经过这个链接发送任意数量的数据。SSE支持ajax轮询、长轮询和HTTP流,能在断开链接时自动肯定什么时候从新链接。微信小程序

  3. 为何须要WebSocket?浏览器

    (1) HTTP协议的局限缓存

    • HTTP协议是一种单向的网络协议,通讯只能由客户端发起,服务器没法主动向客户端推送信息。
    • HTTP协议是无状态的,客户端向服务器发送请求时,每次都要重读发送鉴别信息。

    (2) 轮询、HTTP流、SSE方式存在局限性:

    • ajax轮询:服务器在某个时间段没有数据更新时,会返回相同的数据,浪费带宽,下降CPU的利用率
    • 长轮询:服务端数据更新较快时,需等待客户端发送请求才可返回数据,存在客户端处理数据、请求创建链接和网络延时等时差问题
    • HTTP流:管理链接比较容易出错。
    • SSE:只适用于服务器到客户端的单向推送,如比赛成绩。

    WebSocket是一种与服务器进行全双工、双向通讯的信道,专门为快速传输小数据设计。适用于聊天室等须要双向通讯的场景。

  4. WebSocket的特色

    (1) 双向通讯,服务器能够主动向客户端推送信息,客户端也能够主动向服务器发送信息

    (2) 创建在TCP协议之上

    (3) 与HTTP协议有着良好的兼容性

    (4) 数据格式比较轻量,性能开销小,通讯高效

    (5) 能够发送文本,也能够发送二进制数据

    (6) 没有同源限制,是否与某个域中的页面通讯,彻底取决于服务器(经过握手信息能够知道请求来自何方)

    (7) 协议标识符为wswss,服务器网址就是URL

  5. WebSocket协议与HTTP协议的联系和区别

    (1) 联系

    • 二者都创建在TCP协议之上,经过TCP传递数据。
    • 为了兼容现有浏览器的握手规范,WebSocket须要借用HTTP协议完成握手阶段。

    (2)区别

    WebSocket HTTP
    是HTML5新增的一种通讯协议 与HTML无直接关系
    双向通讯 单向通讯
    持久链接,整个通信过程创建在一次链接中 非持久链接,每次请求要从新创建链接
  6. 创建WebSocket链接的过程

    客户端向服务器发送一个升级协议的HTTP请求,这个请求头部包含ConnectionUpgrade字段,表示客户端须要使用WebSocket协议。服务器将HTTP协议升级成WebSocket协议后返回客户端响应数据,即完成了握手阶段,创建了WebSocket链接,这个链接会持续存在,直到客户端或服务器主动关闭链接。

  7. WebSocket的使用

    (1) 使用WebSocket构造函数建立WebSocket对象

    var ws = new WebSocket('wss://wx.douyucdn.cn')
    复制代码

    (2) 添加事件处理程序

    ws.onopen = function() {
      // 调用send()方法发送数据
      ws.send('发送数据');
    }
    ws.onmessage = function(event) {
      // 处理接收到的数据
      var receive_msg = event.data;
    }
    ws.onerror = function() {
      // 出错处理
      ws.close();
    }
    ws.onclose = function() {
      // 关闭WebSocket
    }
    复制代码
  8. WebSocket的应用

    双向通讯,如聊天室。

    (1) 微信小程序对WebSocket进行了封装,wx.connectSocket()能够理解为建立了一个WebSocket实例SocketTask

    (2) socket.io支持WebSocket、轮询、HTTP流等方式。

  9. WebSocket的降级方案

    WebSocket协议不一样于HTTP,须要创建和维护WebSocket服务器。若是现有服务器不能用于WebSocket通讯,能够组合使用XHRSSE实现双向通讯。【WebSocket至关于在SSE的基础上增长了send()方法】


详解:

  1. HTTP流的实现:

    • 服务端

      <?php
          $i = 0;
          while(true) {
              // 输出一些数据,而后当即刷新输出缓存
              echo "Number is $i";
              flush();
              
              // 等待几秒钟
              sleep(10);
              
              $i++;
          }
      ?>
      复制代码
    • 浏览器

      function createStreamingClient(url, progress, finished){
        var xhr = new XMLHttpRequest(),
          received = 0;
        
        xhr.open("get", url, true);
        xhr.onreadystatechange = function(){
          var result;
          if (xhr.readyState == 3){
            //只取得最新数据并调整计数器
            result = xhr.responseText.substring(received);
            received += result.length;
            //调用 progress 回调函数
            progress(result);
          } else if (xhr.readyState == 4){
            finished(xhr.responseText);
          }
        };
        xhr.send(null);
        return xhr;
      }
      
      var client = createStreamingClient("streaming.php", function(data){
          alert("Received: " + data);
        }, function(data){
          alert("Done!");
        });
      复制代码
  2. SSE API

    (1) 建立一个EventSource对象

    var source = new EventSource('myevents.php');
    复制代码

    (2) 添加事件处理程序

    source.onopen = function() {}
    source.onmessage = function(event) {
      // 处理数据
      var data = event.data;
    }
    source.onerror = function() {
      // 出错处理
      source.close();
    }
    复制代码

    (3) 属性

    • readyState属性:链接的状态
      • 0:表示正在链接
      • 1:打开了链接
      • 2:关闭了链接

    (4) 方法

    • close():强制当即断开链接而且再也不从新链接。默认状况下,EventSource对象会保持与服务器的活动链接,若是链接断开,还会从新链接。

    注:SSE方式服务器返回的数据是流信息,响应的MIME类型必须是text/event-stream,即设置响应头部:

    Content-Type: text/event-stream
    复制代码
  3. HTTP与WebSocket的生命周期

    image

  4. WebSocket握手的请求头和响应头

    请求中的header:

    • Connection: Upgrade:指示这是一个升级请求
    • Upgrade: websocket:表示升级为websocket协议
    • Sec-WebSocket-Key:向服务器提供所需的信息,确认客户端有权请求升级到WebSocket,防止滥用。此头部由客户端自动生成,没法经过XMLHttpRequest.setRequestHeader()方法添加。
    • Sec-WebSocket-Protocol:以优先顺序指定客户端要使用的一个或多个协议
    • Sec-WebSocket-Version:指定客户端但愿使用的WebSocket协议版本
    • Sec-WebSocket-Extensions:指定要求服务器使用的一个或多个WebSocket扩展

    服务端响应中的header:

    • Connection: Upgrade
    • Upgrade: websocket:和Connection一块儿表示服务器已成功切换协议
    • Sec-WebSocket-Accept:返回根据请求头中Sec-WebSocket-Key字段值生成的值
    • Sec-WebSocket-Protocol:返回客户端指定使用的全部协议中支持的第一个协议
    • Sec-WebSocket-Version:服务器若是支持客户端要求的协议版本,则响应头中不包含这个字段。不然,服务端将返回一个错误,并在响应头中以此字段返回服务器支持的协议列表
    • Sec-WebSocket-Extensions:MDN文档中没有明确指明,私觉得与Sec-WebSocket-Version类似
  5. WebSocket API

    (1) 使用构造函数建立WebSocket对象

    var socket = new WebSocket(url, [protocol]);  // protocol指定了可接收的子协议
    复制代码

    (2) 属性

    • WebSocket.readyState:返回实例对象的当前状态
      • 0:对应WebSocket.CONNECTING,正在链接
      • 1:对应WebSocket.OPEN,链接成功
      • 2:对应WebSocket.CLOSING,正在关闭链接
      • 3:对应WebSocket.CLOSED,链接关闭,或打开链接失败
    • WebSocket.bufferedAmount:表示队列中等待传输的UTF-8字节数
    • WebSocket.onopen
    • WebSocket.onmessage
    • WebSocket.onerror
    • WebSocket.onclose
    • WebSocket.binaryType
    • WebSocket.protocol
    • WebSocket.url

    (3) 事件

    事件 事件处理程序 描述
    open Socket.onopen 链接创建时触发
    message Socket.onmessage 客户端接收服务端数据时触发
    error Socket.onerror 通讯发生错误时触发
    close Socket.onclose 链接关闭时触发

    (4) 方法

    • WebSocket.send(data):发送数据

    • WebSocket.close:关闭链接

  6. WebSocket在项目中的应用:

    • 微信斗鱼小程序tcp/TcpClient.js使用wx.connectSocket返回WebSocket实例SocketTask
    • 主站代码@shark/net/lib/tcp/webSocket.js直接调用WebSocket构造函数建立WebSocket实例

参考:

【阮一峰】WebSocket教程:www.ruanyifeng.com/blog/2017/0…

【知乎】WebSocket是什么原理?为何能够实现持久链接?www.zhihu.com/question/20…

【掘金】WebSocket介绍以及node+socket-io实现聊天室功能:juejin.im/entry/5ab37…

【MDN】协议升级机制:developer.mozilla.org/zh-CN/docs/…

【MDN】WebSocket:developer.mozilla.org/en-US/docs/…

【菜鸟教程】HTML5 WebSocket:www.runoob.com/html/html5-…

【HTML5】全双工通讯的WebSocket:halfrost.com/websocket/

【socket.io】socket.io:socket.io/get-started…

【JavaScript高级程序设计】第21章21.5节

相关文章
相关标签/搜索