WebSocket通信

197 阅读2分钟

若是uniapp开发的应用,请参考

step1|✨ 封装WebSocket

@/utils/websocket.js

import ElementUI from 'element-ui';
var websock = null;
let rec; //断线重连后,延迟5秒重新创建WebSocket连接  rec用来存储延迟请求的代码
let isConnect = false; //连接标识 避免重复连接
let checkMsg = "heartbeat"; //心跳发送/返回的信息 服务器和客户端收到的信息内容如果如下 就识别为心跳信息 不要做业务处理

var globalCallback = function() {};

let createWebSocket = (data) => {
  try {
    var ws = "ws://www.okwin.com.cn/message/websocket";
    websock = new WebSocket(ws);
    initWebSocket(data); //初始化websocket连接
  } catch (e) {
    console.log("尝试创建连接失败");
    reConnect(); //如果无法连接上webSocket 那么重新连接!可能会因为服务器重新部署,或者短暂断网等导致无法创建连接
  }
};

//定义重连函数
let reConnect = () => {
  console.log("尝试重新连接");
  if (isConnect) return; //如果已经连上就不在重连了
  rec && clearTimeout(rec);
  rec = setTimeout(function() {
    // 延迟5秒重连  避免过多次过频繁请求重连
    createWebSocket();
  }, 5000);
};
//设置关闭连接
let closeWebSocket = () => {
  websock.close();
};
//心跳设置
var heartCheck = {
  timeout: 60000, //每段时间发送一次心跳包 这里设置为60s
  timeoutObj: null, //延时发送消息对象(启动心跳新建这个对象,收到消息后重置对象)

  start: function() {
    this.timeoutObj = setTimeout(function() {
      if (isConnect) websock.send(checkMsg);
    }, this.timeout);
  },

  reset: function() {
    clearTimeout(this.timeoutObj);
    this.start();
  }
};

// 初始化websocket
function initWebSocket(data) {
  // ws地址 -->这里是你的请求路径
  let ws = data.type == 1 ? `ws://www.okwin.com.cn:9089/websocket/${data.id}` : `ws://www.okwin.com.cn/message/websocket/socket.io/?transport=websocket&type=1&userId=${data.id}`
  websock = new WebSocket(ws);
  websock.onmessage = function(e) {
    websocketonmessage(e,data.type);
  };
  websock.onclose = function(e) {
    console.log(e);
    isConnect = false; //断开后修改标识
    console.log("connection closed (" + e.code + ")");
  };
  websock.onopen = function() {
    console.log("连接成功");
    // heartCheck.start();
  };

  // 连接发生错误的回调方法
  websock.onerror = function() {
    console.log("WebSocket连接发生错误");
    isConnect = false; //连接断开修改标识
    reConnect(); //连接错误 需要重连
  };
}

// 实际调用的方法
function sendSock(agentData, callback) {
  globalCallback = callback;
  if (websock.readyState === websock.OPEN) {
    // 若是ws开启状态
    websocketsend(agentData);
  } else if (websock.readyState === websock.CONNECTING) {
    // 若是 正在开启状态,则等待1s后重新调用
    setTimeout(function() {
      sendSock(agentData, callback);
    }, 1000);
  } else {
    // 若未开启 ,则等待1s后重新调用
    setTimeout(function() {
      sendSock(agentData, callback);
    }, 1000);
  }
}

function getSock(callback) {
  globalCallback = callback;
}
// 数据接收
function websocketonmessage(e,type) {
  console.log(e.data);
  if(type == 1) {
    console.log('收到消息'+type,e.data)
    ElementUI.Notification({
      title: '',
      message: e.data,
      type: 'success',
      duration: 3000,
    })
  }else{
    if(e.data.indexOf('user') != -1){
      let info = JSON.parse(e.data.replace(e.data.substring(0,e.data.lastIndexOf('[')),''))
      console.log('收到消息'+type,info[1].message)
      ElementUI.Notification({
        title: '',
        message: info[1].message,
        type: 'success',
        duration: 3000,
      })
    }
  }
  // let O_o = JSON.parse(decodeUnicode(e.data));

  // if (!O_o) {
  //   heartCheck.reset();
  // } else {
    
  //   if (O_o.msg == "open success") {
  //     sessionStorage.setItem("wid", O_o.wid);
  //   } else {
  //     console.log(O_o);
  //     globalCallback(O_o);
  //   }
  // }

  // globalCallback(JSON.parse(e.data))
  // function decodeUnicode(str) {
  //   str = str.replace(/\\/g, "%");
  //   //转换中文
  //   str = unescape(str);
  //   //将其他受影响的转换回原来
  //   str = str.replace(/%/g, "\\");
  //   //对网址的链接进行处理
  //   str = str.replace(/\\/g, "");
  //   return str;
  // }

}

// 数据发送
function websocketsend(agentData) {
  console.log(JSON.stringify(agentData));
  websock.send(JSON.stringify(agentData));
}

// 将方法暴露出去
export { createWebSocket, closeWebSocket, sendSock, getSock};

step2|✨ 挂载到Vue.prototype上

// 在main.js中
import * as websocket from '@/utils/websocket';
Vue.prototype.$websocket = websocket

step3|✨ 使用

  1. 在登录成功后,调用this.$websocket.createWebSocket()
  2. 退出登录后,调用this.$websocket.closeWebSocket()