简单丶靠谱的保证websocket客户端不断开

实现方式

基于心跳:
客户端发送数据包给服务器,服务器再发给客户端。
基本上大部分文章的心跳都是这样的,但我不想用这种方式。

原因:
客户端发送数据包给服务器,此时客户端知道自己断开了吗?
答案: 知道

那么还要服务器再发给客户端,多此一举,多此一举也就算了,维护的代码还要很多。

js, 基于readyState (不靠谱 看评论)

readyState: developer.mozilla.org/en-US/docs/W...

class Ws {
    static that() {
        if (this.instance === undefined) {
            this.instance = new this()
        }
        return this.instance
    }

    start() { // 启动ws客户端
        this.connect()
        setInterval(() => this.heartbeat(), 3000)
    }

    heartbeat() { // 心跳
        const readyState = this.ws_client.readyState
        console.log("readyState " + readyState)
        this.ws_client.send('hello') // 断线可以加快知道
        if (readyState !== WebSocket.OPEN) {
            console.log("断开重链接")
            this.connect()
        }
    }

    connect() { // 链接
        const ws_url = "ws://124.222.224.186:8800"
        this.ws_client = new WebSocket(ws_url)
    }

    close() {
        this.ws_client.close()
        return "close"
    }

}


Ws.that().start()



// 测试关闭重链接 随机1-20秒断开链接
var testClose = async () => {
    const ms = () => Math.ceil(Math.random() * 20) * 1000
    while (true) {
        const close_res = await new Promise(resolve =>
            setTimeout(() => resolve(Ws.that()
                .close()), ms()) // 随机0-20秒   
        )
        console.log(close_res)
    }
}
testClose()

将代码上面的代码复制到控制台即可测试。
ps: 别在https的网站用控制台,因为:ws:http资源。

uniapp

uni.sendSocketMessage(object) 返回一个 promise,根据其返回结果就知道是否断开链接。

const res = await uni.sendSocketMessage({
  data: "hello"
})
const error = res[0]
if(error !== null){ // 不是空 就是有错误信息 比如断开链接  直接重链即可
    console.log(error)
    this.connect()
}

golang

    for {
        message := []byte("hello")
        go func() {
            defer func() {
                if r := recover(); r != nil {
                    fmt.Println("心跳检测错误", r) // 发送数据给服务器失败
                    go initConnect() // 重链服务器
                }
            }()
            WsClient.WriteMessage(websocket.TextMessage, message)
        }()
        time.Sleep(time.Second * 3) // 3秒发一次数据
    }
本作品采用《CC 协议》,转载必须注明作者和本文链接
专心学习不瞎搞
讨论数量: 4

客户端的环境,比实际想象中要复杂得多,光一个网络断开都有N种原因,通过发 ping 算是较为稳妥的方式。实际测试过,webscoket 连接上,拔掉网线,浏览器上得很久才知道连接断开。

9个月前 评论
Hachiko (作者) 9个月前
lyxxxh (楼主) 9个月前
lyxxxh (楼主) 9个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
87
粉丝
105
喜欢
480
收藏
719
排名:109
访问:8.7 万
私信
所有博文
社区赞助商