美文网首页
Websocket详解和封装

Websocket详解和封装

作者: 扶得一人醉如苏沐晨 | 来源:发表于2023-03-21 10:14 被阅读0次

    一、 websocket 是什么?

    websocket 是一种网络通信协议,与 http 语义一样,但功能不一样
    http 也是一种网络通信协议,为什么不用 http 而用 websocket ?

    二、websocket 与 http 有什么区别?

    websocket 通信可由服务器发起,也可以由客户端发起。可以实现客户端与服务端长连接
    http 通信只能由客户端发起。


    image

    三、WebSocket 触发事件

    以下是 WebSocket 对象的相关事件。


    image

    四、WebSocket 方法

    假定我们使用了以上代码创建了 Socket 对象:this.Socket.close()/this.Socket.send()


    image

    WebSocket 组件封装(包含健康检查和心跳机制)

    <template></template>
    
    <script>
    import { mapGetters } from "vuex";
    export default {
      data () {
        return {
          // ws
          maxReconnect: 3, // 最大重连次数,-1代表无限重连
          reconnectTime: 0, // 重连尝试次数
          socket: "",
          uri: "",
          lockReconnect: false,
          timer: null,
          heartbeat: null,
          heartbeatTimeOut: null,
        };
      },
      computed: {
        ...mapGetters(["userInfo"]),
      },
      beforeDestroy () {
        this.destroyedWs();
      },
      methods: {
        destroyedWs () {
          console.log("ws销毁");
          // 关闭使用close方法关闭socket
          if (this.socket) {
            this.socket.close();
          }
          this.socket = null;
          // 清除定时器
          this.timer = null;
          clearInterval(this.timer);
          clearTimeout(this.heartbeat);
          this.heartbeat = null;
          clearTimeout(this.heartbeatTimeOut);
          this.heartbeatTimeOut = null;
        },
       //初始化方法
        init () {
          this.initWebSocket();
        },
        // 初始化WebSocket
        initWebSocket () {
          if (typeof WebSocket === "undefined") {
            alert("您的浏览器不支持socket");
          } else {
            const uri =
              "ws://" +
              "192.168.0.114:8686" +
              "/mqtt-print/imserver/" +
              this.userInfo.userId;
            // 实例化socket
            this.socket = new WebSocket(uri);
            // 监听socket连接
            this.socket.onopen = this.open;
            // 监听socket错误信息
            this.socket.onerror = this.error;
            // 监听socket消息
            this.socket.onmessage = this.getMessage;
            // 连接关闭
            this.socket.onclose = this.close;
          }
        },
        open: function () {
          console.log("socket连接成功");
          //开启心跳
          this.startHeartbeat();
        },
        error: function () {
          console.log("连接错误");
          //重连
          this.reconnect();
        },
        getMessage: function (msg) {
          const text = msg.data;
          //收到服务器信息,心跳重置并发送
          this.startHeartbeat();
          if (text.indexOf("ping") > 0) {
            return;
          }
          this.$emit("getMessage", text);
        },
        send: function (params) {
          this.socket.send(params);
        },
        close: function () {
          console.log("socket已经关闭");
        },
        /**
         * 重新连接(无限重连)
         */
        reconnect () {
          if (this.socket.readyState === 1) {
            // 如果状态等于1代表 websocket连接正常
            return;
          }
          if (
            this.lockReconnect ||
            (this.maxReconnect !== -1 && this.reconnectTime >= this.maxReconnect)
          ) {
            return;
          }
    
          // 让重连锁变为true,阻止进入下一个循环
          this.lockReconnect = true;
          setTimeout(() => {
            this.reconnectTime++;
            console.log("尝试重连");
            // 建立新连接
            this.initWebSocket();
            this.lockReconnect = false;
          }, 5000);
        },
        /**
         * 开启心跳
         */
        startHeartbeat () {
          const webSocket = this.socket;
          // 清空定时器
          clearTimeout(this.heartbeat);
          this.heartbeat = null;
          clearTimeout(this.heartbeatTimeOut);
          this.heartbeatTimeOut = null;
          // 延时发送下一次心跳
          // console.log("心跳开启");
          this.heartbeat = setTimeout(() => {
            // 如果连接正常
            // console.log("连接状态", webSocket.readyState);
            if (webSocket.readyState === 1) {
              //这里发送一个心跳,后端收到后,返回一个心跳消息,
              let params = JSON.stringify({
                type: "ping",
                toUserId: this.userInfo.userId,
              });
              webSocket.send(params);
              // 心跳发送后,如果服务器超时未响应则断开,如果响应了会被重置心跳定时器
              this.heartbeatTimeOut = setTimeout(() => {
                webSocket.close();
                // 响应超时时间
              }, 10 * 1000);
            } else {
              // 否则重连
              this.reconnect();
            }
            // 心跳间隔时间是30s
          }, 30 * 1000);
        },
      },
    };
    </script>
    

    相关文章

      网友评论

          本文标题:Websocket详解和封装

          本文链接:https://www.haomeiwen.com/subject/ltcbldtx.html