zoukankan      html  css  js  c++  java
  • WebSocket属性的简介及使用

    WebSocket

    浏览器通过JavaScript向服务器发出建立WebSocket链接的请求,链接建立后,客户端和服务器端就可以通过TCP链接直接交互数据。WebSocket链接后可以通过send()方法来向服务器发送数据,并通过onnessage事件来接受服务器返回的数据。

    创建WebSocket对象

    let ws = new WebSocket(server);
    

    WebSocket属性

    属性 描述
    ws.readyState WebSocket.CONNECTING: 0正在链接
    WebSocket.OPEN: 1 链接成功,可以通信
    WebSocket.CLOSING: 2 链接正在关闭
    WebSocket.CLOSED: 3 链接已经关闭,或者打开链接失败
    ws.bufferedAmount 只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。
    ws.onopen 连接建立时触发
    ws.onmessage 客户端接收服务端数据时触发
    ws.onerror 通信发生错误时触发
    ws.onclose 连接关闭时触发
    ws.binaryType 指定有链接所传递的二进制数据类型(可选值:blobarraybuffer)

    WebSocket 方法

    方法 描述
    ws.send() 使用链接发送数据
    ws.close() 关闭链接

    WebSocket使用

    创建WebSocket实例

    首先判断当前浏览器是否支持WebSocket,如果支持则创建WebSocket实例,并初始化事件函数。

    let ws = null;
    const server = `ws://xxx.xx.xxx.xxx:xxxx`;// WebSocket服务地址
    let createWebSocket = (server) => {
      try {
        if(window["WebSocket"]){
          ws = new WebSocket(server)
        }else if(window["MozWebSocket"]){
          ws = new MozWebSocket(server)
        } else  {
          Notification({message:"当前浏览器不支持websocket协议,建议使用Chrome浏览器",type:"success"})
        }
        initEventHandle()// 连接建立时触发
      } catch (e) {
        console.log("ERR-----------捕获异常", e)
      }
    };
    

    初始化事件函数

    onerroronclose进行报错或链接断开后的一下业务逻辑操作(如:重连操作)
    onopen:初始化状态(如:心跳检测、重连次数)
    onmessage:对服务器发送的消息做处理

    let initEventHandle = () => {
      // 连接报错
      ws.onerror = function (evt, e) {
        console.log("连接报错");
      };
      // 连接关闭
      ws.onclose = function (evt) {
        console.log("连接关闭---" + new Date().toLocaleTimeString());
      };
      // 链接成功
      ws.onopen = function (evt) {
        console.log("链接成功");
      };
      // 接受数据
      ws.onmessage = function (evt) {
         console.log("收到消息");
      };
    };
    
    重连机制

    当浏览器断开WebSocket链接时或链接失败时,会出发oncloseonerror事件。我们可以在oncloseonerror中调用重连方法。为了避免重连方法的过多请求,可以定义一个状态来控制,也可以设置最大重连次数。

    let count = 0;// 记录次数
    let lockReconnect = false;// 避免ws重复连接
    let reconnect = (server) => {
      if (count >= 5) return console.log("超出重连次数!");
      if (lockReconnect) return false;
      lockReconnect = true;
      setTimeout(function () {     // 设置延迟避免请求过多
        console.log("6----------开始重连");
        lockReconnect = false;
        count++;
      }, 5000);
    };
    

    在这里插入图片描述

    心跳检测

    为了保证WebSocket与服务器之间正常通信,可以每隔一段时间通过send()方法向服务器发送一个心跳信息。在onmessage拿到返回的心跳就说明连接正常。(服务器收到信息会返回相应的信息)

    const heartCheck = {
      timeout: 25000,        // 设置心跳时间
      timeoutObj: null,
      serverTimeoutObj: null,
      reset: function () {
        clearTimeout(this.timeoutObj);
        clearTimeout(this.serverTimeoutObj);
        return this;
      },
      start: function () {
        const self = this;
        this.timeoutObj = setTimeout(function () {
          // 这里发送一个心跳,后端收到后,返回一个心跳消息,onmessage拿到返回的心跳就说明连接正常
          ws.send("ping----------Ping");
          self.serverTimeoutObj = setTimeout(function () {
            // 如果超过一定时间还没重置,说明后端主动断开了
            // 如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
            ws.close();
          },self.timeout)
        },this.timeout)
      }
    };
    

    监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。

    window.onbeforeunload = function () {
      ws.close();
    };
    

    在Vue中使用WebSocket

    main.js中引入全局并挂载到Vue原型上。

    import socket from "@/utils/webSocket";
    Vue.prototype.startWebSocket  = socket.startWebSocket;
    

    完整代码:

    // webSocket.js
    import {Notification} from "element-ui";
    import { getToken } from '@/utils/auth';
    
    let count = 0;// 记录计数
    let lockReconnect = false;//避免ws重复连接
    const text1 = "您有新的订单,请及时处理!";
    let ws = null;// 判断当前浏览器是否支持WebSocket
    const server = `ws://xxx.xx.xxx.xxx:xxxx?Admin-Token=${getToken()}`;// WebSocket服务地址
    // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function () {
      ws.close();
    };
    // 重连
    let reconnect = (server) => {
      if (count >= 5) return console.log("超出重连次数!");
      if (lockReconnect) return false;
      lockReconnect = true;
      setTimeout(function () {     //没连接上会一直重连,设置延迟避免请求过多
        createWebSocket(server);
        lockReconnect = false;
        count++;
      }, 5000);
    };
    // 创建实例websocket
    let createWebSocket = (server) => {
      try {
        if('WebSocket' in window){
          ws = new WebSocket(server)
        }else if('MozWebSocket' in window){
          ws = new MozWebSocket(server)
        } else  {
          Notification({message:"当前浏览器不支持websocket协议,建议使用现代浏览器",type:"success"})
        }
        // 连接建立时触发
        initEventHandle()
      } catch (e) {
        console.log("ERR-----------捕获异常", e)
      }
    };
    // 初始化事件函数
    let initEventHandle = () => {
      // 连接报错
      ws.onerror = function (evt, e) {
        reconnect(server)
      };
      // 连接关闭
      ws.onclose = function (evt) {
        console.log("连接关闭---" + new Date().toLocaleTimeString());
        reconnect(server)
      };
      // 链接成功
      ws.onopen = function (evt) {
        heartCheck.reset().start();// 心跳检测重置
        count = 0;// 重置重连次数
      };
      // 接受数据
      ws.onmessage = function (evt) {// 如果获取到消息,心跳检测重置
        heartCheck.reset().start();// 拿到任何消息都说明当前连接是正常的
        let eventData  = undefined;
        try {
          eventData = JSON.parse(evt.data);
          handMsg(eventData)
        }catch (e) {
          console.log("捕获异常: 当前返回的数据不能解析;");
          console.log("内容:" + evt.data)
        }
      };
    };
    // 心跳检测
    const heartCheck = {
      timeout: 25000,        // 设置心跳时间
      timeoutObj: null,
      serverTimeoutObj: null,
      reset: function () {
        clearTimeout(this.timeoutObj);
        clearTimeout(this.serverTimeoutObj);
        return this;
      },
      start: function () {
        const self = this;
        this.timeoutObj = setTimeout(function () {
          // 这里发送一个心跳,后端收到后,返回一个心跳消息,onmessage拿到返回的心跳就说明连接正常
          ws.send("ping--------------Ping");
          self.serverTimeoutObj = setTimeout(function () {
            // 如果超过一定时间还没重置,说明后端主动断开了
            // 如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
            ws.close();
          },self.timeout)
        },this.timeout)
      }
    };
    // 处理消息
    let handMsg = (eventData) => {
      if (ws.readyState === WebSocket.OPEN) {
        if (eventData.code === "2000" && eventData.type === "order_notice") {
          Notification({message: text1,type:"warning"})
        }
      }
    };
    let startWebSocket = () => {
      createWebSocket(server)
    };
    export default { startWebSocket }
    

    效果图:
    在这里插入图片描述

  • 相关阅读:
    BZOJ 1021 循环的债务
    BZOJ 1019 汉诺塔
    BZOJ 1018 堵塞的交通
    BZOJ 1017 魔兽地图
    BZOJ 1016 最小生成树计数
    Luogu 3008 [USACO11JAN]道路和飞机Roads and Planes
    Luogu 3625 [APIO2009]采油区域
    Luogu 4139 上帝与集合的正确用法
    Luogu 3629 [APIO2010]巡逻
    Luogu 3626 [APIO2009]会议中心
  • 原文地址:https://www.cnblogs.com/BeautifulGirl230/p/14108137.html
Copyright © 2011-2022 走看看