当前位置:   article > 正文

websocket超时重连、心跳检测

websocket超时

websocket

在单个TCP连接上进行全双工通信的协议,可以实现服务端和客户端双向推送信息的协议。我们在使用webscoket通信时必须要注意的问题超时重连和心跳检测。
超时重连:当出现错误时客户端尝试重新连接websocket。
心跳检测:客户端长时间没接收到服务端消息,就向服务端发送请求,查看服务端是否还在,如果服务端在规定时间未回复消息则表明服务端由于某种原因中断了,那么客户端也就可以中断连接了。当然下面代码可以通过reconnect再次选择重连。

class WebSocketClient {
    #ws = null
    #needReconnect
    #count
    constructor(options) {
        this.url = options.url
        this.#needReconnect = false//是否需要重连
        this.#initWS()//启动ws
        this.watch = options.watch || true//是否开启心跳
        this.reconnectCountLimit = options.reconnectCountLimit ||3 //重连次数
        this.#count = 0 //重连次数计数
        this.reconnectTime = null//重连计时器
        this.reconnectInterval = options.reconnectInterval || 5000//重连时间间隔
        this.lastMessageTime = 0 //记录上次收到信息的时间 ->暂时没使用
        this.heartDeadline = options.heartDeadline || 10000//心跳检测截止时间 每次收到信息后将在该时间后发送心跳消息,在该时间内未收到信息就终端ws连接
        this.heartCloseTime = null //心跳关闭计时器
        this.checkHeartTime = null  //发送心跳消息计时器
    }
    get ws() {
        return this.#ws
    }
    //初始化websocket
    #initWS() {
        this.#ws = new WebSocket(this.url)
        this.#ws.addEventListener('open', (e) => {
            this.initState()
            this.#ws.send(`${JSON.stringify({ name: 'xxx', job: '前端高级工程师', salary: 41000 })}`)
        })
        this.#ws.addEventListener('close', (e) => {
            console.log('链接关闭')
        })
        this.#ws.addEventListener('error', (e) => {
            console.log('ws错误,开启重连')
            this.#needReconnect = true
            this.reconnect()
        })
        this.#ws.addEventListener('message', (e) => {
            this.lastMessageTime = new Date().getTime()
            console.log(e.data, 'I am client。I received your message')
            this.watch && this.heartBeat()//启动心跳检测

        })
    }
    //重连
    reconnect() {
        if (this.#needReconnect && this.#count < this.reconnectCountLimit) {
            this.reconnectTime = setTimeout(() => {
                console.log('重连')
                this.#count++
                this.#initWS()
            }, this.reconnectInterval);
            return
        }
        this.initState()
    }
    //初始化数据
    initState() {
        this.#needReconnect = false
        this.#count = 0
        this.reconnectTime && clearInterval(this.reconnectTime)
    }
    closeCheckHeart() {
        clearTimeout(this.checkHeartTime)
        clearTimeout(this.heartCloseTime)
    }
    send(data) {
       this.#ws.send(data) 
    }
    //心跳检测
    heartBeat() {
        const checkHeart = () => {
            return new Promise((resolve) => {
                //心跳检测 当上一次交换信息时间和现在间隔heartLimit时3s后开启心跳检测
                console.log(new Date(this.lastMessageTime).toLocaleString(),'上次收到时间');
                this.closeCheckHeart()
                this.checkHeartTime = setTimeout(() => {
                    if (this.#ws.readyState === 1) {
                        console.log('检测心跳');
                        this.#ws.send(JSON.stringify({
                            type: 'heart'
                        }))
                        this.heartCloseTime = setTimeout(() => {
                            console.log('超时关闭')
                            this.#ws.close()
                        }, this.heartDeadline)
                        resolve()
                    } else {
                        checkHeart()
                    }
                }, this.heartDeadline)
            })
        }
        checkHeart()
    }
}
const ws = new WebSocketClient({ url:'ws://localhost:8888'})

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97

import { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 8888 });

wss.on('connection', function connection(ws) {
  ws.on('message', function message(data) {
    const res = data.toString()
    console.log(res)
    if (res.startsWith('{') && JSON.parse(res)?.type === 'heart') {
      // ws.send('{heart:exist}')
    }
  });
  wss.clients.forEach(client => {
    client && client.send('广播信息')
  })
  ws.send('I am service');
  setTimeout(() => {
    ws.send('xxx');
  },10000)
});
wss.onopen = function (e) {
  console.log('服务端链接');
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/242073
推荐阅读
相关标签
  

闽ICP备14008679号