WebSocket 心跳检测、重连、订阅、退订、消息发送

Client,js

class WsClient {
  constructor(url) {
    // this.client=new WebSocket(url);
    this.url = url;
    this.isAlive = true;
    this.ping = null;
    this.heartbeatTimeout = null;
    this.callbackMap = new Map();
    this.connect();
  }

  // 连接
  connect() {
    this.client = new WebSocket(this.url);
    this.client.onopen = (e) => {
      // console.log('onopen')
      this.heartbeat();
    };
    this.client.onmessage = (e) => {
      // console.log('onmessage',e.data)
      this.handleMessage(JSON.parse(e.data));
    };
    this.client.onerror = (e) => {
      // console.log('onerror')
      this.reconnect();
    };
    this.client.onclose = (e) => {
      // console.log('onclose')
      this.reconnect();
    };
  }

  // 重连
  reconnect() {
    this.isAlive = false;
    clearTimeout(this.heartbeatTimeout);
    this.heartbeatTimeout = setTimeout(() => {
      if (this.isAlive === false) {
        this.client.close();
        this.connect();
      }
    }, 20000 + 2000);
  }

  // 心跳检测
  heartbeat() {
    this.isAlive = true;
    clearInterval(this.ping);
    this.ping = setInterval(() => {
        if(this.isAlive){
            this.client.send(JSON.stringify({ type: "ping" }));
        }
    }, 30000);
  }

  // 发送消息
  sendMessage(mesg) {
    if (this.client && this.client.readyState === 1) {
      this.client.send(mesg);
    } else {
      // webscoekt 连接尚未建立
      setTimeout(() => {
        this.sendMessage(mesg);
      }, 1000);
    }
  }

  // 订阅
  subscribe(topic, callback) {
    let calls = this.callbackMap.get(topic) || [];
    calls.push(callback);
    this.callbackMap.set(topic, calls);
    // console.log("subscribe",topic,callback,calls);
  }

  // 退订
  unSubscribe(topic, callback) {
    let calls = this.callbackMap.get(topic) || [];
    if (calls.length === 0) {
      this.callbackMap.delete(topic);
    } else {
      calls = calls.filter((c) => {
        return c != callback;
      });
      this.callbackMap.set(topic, calls);
    }

    // console.log("unSubscribe",topic,callback,calls);
  }

  // 处理 message
  handleMessage(mesg) {
    let { topic, data } = mesg;
    if (topic) {
      let calls = this.callbackMap.get(topic) || [];
      // console.log(topic,data,calls);
      calls.forEach((c) => {
        c(data);
      });
    } else {
      console.error(mesg);
    }
  }
}

let client = new WsClient("ws://localhost:18088");

let testCallback = (data) => {
  console.log(data);
};
client.subscribe("test", testCallback);

client.unSubscribe("test", testCallback);

Server.js

const { WebSocketServer } =require('ws');

const wss = new WebSocketServer({ host:'0.0.0.0',port: 18088 });

wss.on('connection', function connection(ws) {
  ws.on('message', function message(data) {
    console.log('received: %s', data);
  });

  // ws.send('something');
  console.log('connection');
});

setInterval(()=>{
  wss.clients.forEach(c=>{
    let data=JSON.stringify({
      topic:'test',
      data:{
        name:"jiachao",
      }
    })
    c.send(data);
  })
},3000)
// console.log(wss);

本文作者:qfluck

本文链接:https://www.cnblogs.com/qfluck/p/16696588.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   qfluck  阅读(696)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.