记websocket心跳消息问题

前言:在使用settimeout发送心跳消息有问题,有可能是封装的方法没写好或者其他原因吧,不懂呀,最后解决是解决了(最终代码在最下面),就是还是有很多不懂的地方需要摸索探查

一,方法一(settimeout):会出现断连问题

刚开始用的是settimeout定时发送心跳消息,但中途会出现断连

参考的是如下方法:

 //心跳检测
 var heartCheck = {
     timeout: 5000, //1分钟发一次心跳
     timeoutObj: null,
     serverTimeoutObj: null,
     reset: function () {
         clearTimeout(this.timeoutObj);
         clearTimeout(this.serverTimeoutObj);
         return this;
     },
     start: function () {
         var self = this;
         this.timeoutObj = setTimeout(function () {
             //这里发送一个心跳,后端收到后,返回一个心跳消息,
             //onmessage拿到返回的心跳就说明连接正常
             send("ping");
             self.serverTimeoutObj = setTimeout(function () { //如果超过一定时间还没重置,说明后端主动断开了
                 websocket.close(); //如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
             }, self.timeout)
         }, this.timeout)
     }
 }

 // 使用,在连接成功建立的回调方法内使用示例(其他的部分就不写了):
 websocket.onopen = function (event) {
     heartCheck.reset().start();
 }

不知道是因为什么引起的问题,反正心跳消息发着发着某个时候突然就不发了,定时器似乎就像是停止工作了

二、方法二:仍然出现断连

之后又用了一个方法requestAnimationFrame

参考文章是这个:(链接中有个使用方法括号没写会有影响,自己可以改一下试试)

从一次移动端定时器卡死分析JS定时器机制 - 知乎

经过尝试后发现,仍然是某个时刻突然平白无故断开,

我之后再找时间考察一下原因吧......

三、直接使用setInterval处理心跳消息

在这两个方式都还是会存在不稳定或者断开的情况,我开始觉得找寻其他方法

试了下直接用setInterval方法,

连接上直接发送ping消息,之后只要每次后端发动pong消息这边就清除定时器后再次发送ping消息,依靠每次收到的后端发过来的pong消息稳定维持发送。

后面表现也很稳定,连接一整天都不会断,代码如下:

$(function () {
    // 监听网络链接(首次链接不会触发)
    window.addEventListener("online", function () {
        reconnect()
    })
    // 监听网络断开
    window.addEventListener("offline", function () {
        clearInterval(heartBeat);
        websocket.close();

    })
    window.onunload = function (event) {
        // 清除表单输入
        // 清除cookie
        // 撤销订阅的事件和定时器
        // ......
    };




    var uniqueId = "***"
    var websocket = null;
    var lockReconnect = false; //避免ws重复连接
    var time = Date.parse(new Date()) / 1000
    var sign = "***......"
    var url = "ws://1.234.56.78:9999?sign=" + sign + "&zuoxi=" + uniqueId + "&time=" + time
    var heartBeat

    //判断当前浏览器是否支持WebSocket, 主要此处要更换为自己的地址
    if ('WebSocket' in window) {
        connectSocket();
    } else {
        alert('Not support websocket')
    }

    //连接webSocket
    function connectSocket() {
        try {
            time = Date.parse(new Date()) / 1000
            sign = "***......"
            url = "ws://1.234.56.78:9999?sign=" + sign + "&zuoxi=" + uniqueId + "&time=" + time
            websocket = new WebSocket(url);
            initEvent();
        } catch (e) {
            reconnect();
            console.log(e);
        }
    }

    function initEvent() {
        //连接发生错误的回调方法
        websocket.onerror = function (e) {
            reconnect();
            // console.log("ws连接错误!");
        };

        //连接成功建立的回调方法
        websocket.onopen = function (event) {
            send("PING")
            heartBeat = setInterval(function () {
                send("PING")
            }, 10000);
            // ajax查询用户状态
            // ......
            // console.log("ws连接成功!");
        }

        //接收到消息的回调方法
        websocket.onmessage = function (event) {
            if (event.data === 'ping消息过期,客户端将被关闭') {
                clearInterval(heartBeat);
                websocket.close();
                reconnect()
                return
            } else if (event.data == "PONE") {
                clearInterval(heartBeat);
                heartBeat = setInterval(function () {
                    send("PING")
                }, 10000);
                return
            } else if (event.data == "通信ID无效") {
                // 用户已经下线,不可发送消息!
                return
            } else {
                // 用户消息
                var fromUserMsg = JSON.parse(event.data)
                if (fromUserMsg.type == "onLine") {
                    // 用户上线
                    // ......
                } else if (fromUserMsg.type == "offLine") {
                    // 用户下线
                    // ......
                } else {
                   // 用户发了消息
                    // ......
                }
            }


        }

        //连接关闭的回调方法
        websocket.onclose = function (e) {
            clearInterval(heartBeat);
            console.log("ws连接关闭!");
        }
    }

    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function () {
        clearInterval(heartBeat);
        closeWebSocket();
    }

    //关闭连接
    function closeWebSocket() {
        websocket.close();
    }

    //发送消息
    function send(message) {
        if (message == "PING") {
            websocket.send(message);
            return
        }
        let connectId = 123
        var data = {
            class: "消息",
            type: "onMessage",
            text: {
                data: message,
                connectId: connectId,
            }
        }

        websocket.send(JSON.stringify(data));
    }

    //重连
    function reconnect() {
        if (lockReconnect) return;
        lockReconnect = true;
        setTimeout(function () { //没连接上会一直重连,设置延迟避免请求过多
            connectSocket();
            lockReconnect = false;
        }, 100);
    }


    // 为发送按钮绑定鼠标点击事件
    $('body').on('click', "#btnSend", function () {
        var sendTime = new Date().getTime()
        var text = $('#ipt').val().trim()
        if (text.length <= 0) {
            return $('#ipt').val('')
        }

        let sendText = {
            text: text,
            msgNewTime: sendTime
        }
        JSON.stringify(sendText)
        send(sendText)
        // 记录聊天内容
        // 如果用户输入了聊天内容,则将聊天内容追加到页面上显示
        // 重置滚动条的位置
    })

})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
springboot websocket 心跳是为了保证连接的可持续性和稳定性而引入的一种机制。通过发送心跳消息,前后端可以相互检测连接是否正常,如果连接断开或无响应,则可以采取相应的措施进行重连或处理。 在Spring Boot中使用WebSocket实现心跳功能,首先需要引入相关依赖,如在pom.xml文件中添加以下代码: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 接下来,在application.yml文件中进行相关配置,如设置服务器端口和WebSocket相关参数。 然后,创建WebSocketConfig配置类,用于配置WebSocket的相关信息。 在后端代码中,可以使用定时任务来执行WebSocket心跳检测。例如,可以创建一个WebSocketTask类,并使用@EnableScheduling注解启用定时任务功能。在该类中,可以编写定时任务方法,通过发送心跳消息来检测连接状态,并录检测结果。 使用Spring Boot进行单元测试时,可以通过模拟发送心跳消息,来验证WebSocket心跳功能是否正常工作。 总结起来,Spring Boot WebSocket心跳机制是通过配置和定时任务来实现的,通过定时发送心跳消息来检测连接状态,以保证连接的可持续性和稳定性。这样可以确保前后端交互的长连接能够正常运行。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [SpringBoot+WebSocket实战与心跳机制](https://blog.csdn.net/qq_42582773/article/details/127027514)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值