简单丶靠谱的保证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 协议》,转载必须注明作者和本文链接
客户端的环境,比实际想象中要复杂得多,光一个网络断开都有N种原因,通过发 ping 算是较为稳妥的方式。实际测试过,webscoket 连接上,拔掉网线,浏览器上得很久才知道连接断开。