websocket断线重连&&心跳检测


前言

封装websocket 实现断线重连跟心态检测,使用的typeScript去封装

一、服务端实现ws

在nodejs 安装ws库

1.引入库

代码如下(示例):

npm i ws

 服务端实现ws 创建一个server.js 文件 运行ws服务   node .\server.js 



// 引入模块
const WebSocket = require("ws").Server;
const port = 3001;

// 创建服务器
const server = new WebSocket({ port }, () => {
  console.log("websocket服务开启");
});

const connectHandler = (ws) => {
  console.log("客户端连接");
  // 监听客户端出错
  ws.on("error", errorHandler);
  // 监听客户端断开链接
  ws.on("close", closeHandler);
  // 监听客户端发来的消息
  ws.on("message", messageHandler);
};

// 监听接收客户端信息回调
// 注意:因为这里用到this的指向,因此用普通的函数
function messageHandler(data) {
  console.log("messageHandler===>接收客户端消息", JSON.parse(data));
  const { ModeCode } = JSON.parse(data);
  switch (ModeCode) {
    case "message":
      console.log("收到消息");
      // 需要发送信息给客户端以此说明连接成功
      this.send(JSON.stringify(JSON.parse(data)));
      break;
    case "heart_beat":
      console.log("心跳检测");
      // 需要发送信息给客户端以此说明连接成功
      this.send(JSON.stringify(JSON.parse(data)));
      break;
  }
}

// 监听客户端出错回调
const errorHandler = (error) => {
  console.log("errorHandler===>客户端出错", error);
};
// 监听客户端断开连接回调
const closeHandler = (e) => {
  console.log("closeHandler===>客户端断开🔗", e);
};

// 建立连接
server.on("connection", connectHandler);

客户端实现websocket

创建一个socket.ts 文件

class Socket {
  wsUrl;
  constructor(wsUrl: any) {
    this.wsUrl = wsUrl;
  }

  ModeCode = {
    // websocket消息类型
    MSG: "message", // 普通消息
    HEART_BEAT: "heart_beat" // 心跳
  };
  ws: any = null;
  webSocketState: boolean = false; // webSocket的连接状态
  heartBeat = {
    // 心跳连接的时间设置
    time: 5 * 1000, // 心跳时间间隔
    timeout: 3 * 1000, // timeout:心跳超时间隔
    reconnect: 10 * 1000 // 断线重连时间
  };
  reconnectTimer: any = null; // 断线重连时间器

  /**
   * 连接ws
   */
  connectWebSocket() {
    this.ws = new WebSocket(this.wsUrl);
    this.init();
  }
  /*
   * 心跳初始函数
   * @param time:心跳时间间隔
   */
  startHeartBeat(time: Number | string) {
    setTimeout(() => {
      this.ws.send(
        JSON.stringify({
          ModeCode: this.ModeCode.HEART_BEAT,
          msg: new Date()
        })
      );
      this.waitingServer();
    }, time as any);
  }
  // 延时等待服务端响应,通过webSocketState判断是否连线成功
  waitingServer() {
    this.webSocketState = false;
    setTimeout(() => {
      if (this.webSocketState) {
        this.startHeartBeat(this.heartBeat.time);
        return;
      }
      console.log("心跳无响应,已断线");
      try {
        this.ws.close();
      } catch (e) {
        console.log("连接已关闭,无需关闭");
      }
      this.reconnectWebSocket();
    }, this.heartBeat.timeout);
  }
  // 重连操作
  reconnectWebSocket() {
    this.reconnectTimer = setTimeout(() => {
      this.reconnectWs();
    }, this.heartBeat.reconnect);
  }
  //初始化
  init() {
    this.ws.addEventListener("open", () => {
      this.webSocketState = true; //socket状态设置为连接,做为后面的断线重连的拦截器
      this.heartBeat && this.heartBeat.time ? this.startHeartBeat(this.heartBeat.time) : ""; // 是否启动心跳机制
      console.log("开启");
    });
    this.ws.addEventListener("message", (e: any) => {
      console.log(e.data, "eeeee");
      const data = JSON.parse(e.data);
      switch (data.ModeCode) {
        case this.ModeCode.MSG: // 普通消息
          console.log("收到消息" + data.msg);
          break;
        case this.ModeCode.HEART_BEAT: // 心跳
          this.webSocketState = true;
          console.log("收到心跳响应" + data.msg);
          break;
      }
    });
    this.ws.addEventListener("close", (e: any) => {
      this.webSocketState = false; // socket状态设置为断线
      console.log("断开了连接", e);
    });
    this.ws.addEventListener("error", (e: any) => {
      this.webSocketState = false; // socket状态设置为断线
      this.reconnectWebSocket(); // 重连
      console.log("连接发生了错误", e);
    });
  }
  reconnectWs() {
    if (!this.ws) {
      // 第一次执行,初始化
      this.connectWebSocket();
    }
    if (this.ws && this.reconnectTimer) {
      // 防止多个websocket同时执行
      clearTimeout(this.reconnectTimer);
      this.ws.reconnectTimer = null;
      this.connectWebSocket();
    }
  }

  //发送数据
  sendMessage(data: any) {
    this.ws.send(JSON.stringify(data));
  }
  //在其他需要socket地方主动关闭socket
  closeWebSocket(e: any) {
    console.log(e);
    this.ws.close();
    clearTimeout(this.reconnectTimer);
    this.webSocketState = false;
  }
}

export default Socket;

vue 页面使用

//引用
import Scoket from "@/utils/socket";

const socket = new Scoket("ws://localhost:3001");
//发送消息
const onSend = () => {
  console.log("onSend");
  socket.sendMessage(message.value);
};
//连接ws
onMounted(() => {
  socket.connectWebSocket();
});

断开ws服务 断线  启动服务后 自动重连


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值