Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 753|回复: 0

[默认分类] 理解WebSocket心跳及重连机制

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-3-27 09:20:09 | 显示全部楼层 |阅读模式
    理解WebSocket心跳及重连机制
        在使用websocket的过程中,有时候会遇到网络断开的情况,但是在网络断开的时候服务器端并没有触发onclose的事件。这样会有:服务器会继续向客户端发送多余的链接,并且这些数据还会丢失。所以就需要一种机制来检测客户端和服务端是否处于正常的链接状态。因此就有了websocket的心跳了。还有心跳,说明还活着,没有心跳说明已经挂掉了。
    1. 为什么叫心跳包呢?
    它就像心跳一样每隔固定的时间发一次,来告诉服务器,我还活着。
    2. 心跳机制是?
    心跳机制是每隔一段时间会向服务器发送一个数据包,告诉服务器自己还活着,同时客户端会确认服务器端是否还活着,如果还活着的话,就会回传一个数据包给客户端来确定服务器端也还活着,否则的话,有可能是网络断开连接了。需要重连~
    那么需要怎么去实现它呢?如下所有代码:

    1. <html>
    2. <head>
    3.   <meta charset="utf-8">
    4.   <title>WebSocket Demo</title>
    5. </head>
    6. <body>
    7.   <script type="text/javascript">
    8.     // var ws = new WebSocket("wss://echo.websocket.org");
    9.     /*
    10.     ws.onerror = function(e) {
    11.       console.log("已关闭");
    12.     };
    13.     ws.onopen = function(e) {
    14.       console.log("握手成功");
    15.       ws.send("123456789");
    16.     }
    17.     ws.onclose = function() {
    18.       console.log("已关闭");
    19.     }
    20.     ws.onmessage = function(e) {
    21.       console.log("收到消息");
    22.       console.log(e);
    23.     }
    24.     */
    25.    
    26.     var lockReconnect = false;//避免重复连接
    27.     var wsUrl = "wss://echo.websocket.org";
    28.     var ws;
    29.     var tt;
    30.     function createWebSocket() {
    31.       try {
    32.         ws = new WebSocket(wsUrl);
    33.         init();
    34.       } catch(e) {
    35.         console.log("catch");
    36.         reconnect(wsUrl);
    37.       }
    38.     }
    39.     function init() {
    40.       ws.onclose = function () {
    41.         console.log("链接关闭");
    42.         reconnect(wsUrl);
    43.       };
    44.       ws.onerror = function() {
    45.         console.log("发生异常了");
    46.         reconnect(wsUrl);
    47.       };
    48.       ws.onopen = function () {
    49.         //心跳检测重置
    50.         heartCheck.start();
    51.       };
    52.       ws.onmessage = function (event) {
    53.         //拿到任何消息都说明当前连接是正常的
    54.         console.log("接收到消息");
    55.         heartCheck.start();
    56.       }
    57.     }
    58.     function reconnect(url) {
    59.       if(lockReconnect) {
    60.         return;
    61.       };
    62.       lockReconnect = true;
    63.       //没连接上会一直重连,设置延迟避免请求过多
    64.       tt && clearTimeout(tt);
    65.       tt = setTimeout(function () {
    66.         createWebSocket(url);
    67.         lockReconnect = false;
    68.       }, 4000);
    69.     }
    70.     //心跳检测
    71.     var heartCheck = {
    72.       timeout: 3000,
    73.       timeoutObj: null,
    74.       serverTimeoutObj: null,
    75.       start: function(){
    76.         console.log("start");
    77.         var self = this;
    78.         this.timeoutObj && clearTimeout(this.timeoutObj);
    79.         this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
    80.         this.timeoutObj = setTimeout(function(){
    81.           //这里发送一个心跳,后端收到后,返回一个心跳消息,
    82.           console.log("55555");
    83.           ws.send("123456789");
    84.           self.serverTimeoutObj = setTimeout(function() {
    85.             console.log(111);
    86.             console.log(ws);
    87.             ws.close();
    88.             // createWebSocket();
    89.           }, self.timeout);
    90.         }, this.timeout)
    91.       }
    92.     }
    93.     createWebSocket(wsUrl);
    94.   </script>
    95. </body>
    96. </html>
    复制代码


    具体的思路如下:
    1. 第一步页面初始化,先调用createWebSocket函数,目的是创建一个websocket的方法:new WebSocket(wsUrl);因此封装成函数内如下代码:

    1. function createWebSocket() {
    2.   try {
    3.     ws = new WebSocket(wsUrl);
    4.     init();
    5.   } catch(e) {
    6.     console.log("catch");
    7.     reconnect(wsUrl);
    8.   }
    9. }
    复制代码


    2. 第二步调用init方法,该方法内把一些监听事件封装如下:

    1. function init() {
    2.   ws.onclose = function () {
    3.     console.log("链接关闭");
    4.     reconnect(wsUrl);
    5.   };
    6.   ws.onerror = function() {
    7.     console.log("发生异常了");
    8.     reconnect(wsUrl);
    9.   };
    10.   ws.onopen = function () {
    11.     //心跳检测重置
    12.     heartCheck.start();
    13.   };
    14.   ws.onmessage = function (event) {
    15.     //拿到任何消息都说明当前连接是正常的
    16.     console.log("接收到消息");
    17.     heartCheck.start();
    18.   }
    19. }
    复制代码


    3. 如上第二步,当网络断开的时候,会先调用onerror,onclose事件可以监听到,会调用reconnect方法进行重连操作。正常的情况下,是先调用
    onopen方法的,当接收到数据时,会被onmessage事件监听到。
    4. 重连操作 reconnect代码如下:

    1. var lockReconnect = false;//避免重复连接
    2. function reconnect(url) {
    3.   if(lockReconnect) {
    4.     return;
    5.   };
    6.   lockReconnect = true;
    7.   //没连接上会一直重连,设置延迟避免请求过多
    8.   tt && clearTimeout(tt);
    9.   tt = setTimeout(function () {
    10.     createWebSocket(url);
    11.     lockReconnect = false;
    12.   }, 4000);
    13. }
    复制代码


    如上代码,如果网络断开的话,会执行reconnect方法,使用了一个定时器,4秒后会重新创建一个新的websocket链接,重新调用createWebSocket函数,
    重新会执行及发送数据给服务器端。
    5. 最后一步就是实现心跳检测的代码:如下:

    1. //心跳检测
    2. var heartCheck = {
    3.   timeout: 3000,
    4.   timeoutObj: null,
    5.   serverTimeoutObj: null,
    6.   start: function(){
    7.     console.log("start");
    8.     var self = this;
    9.     this.timeoutObj && clearTimeout(this.timeoutObj);
    10.     this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
    11.     this.timeoutObj = setTimeout(function(){
    12.       //这里发送一个心跳,后端收到后,返回一个心跳消息,
    13.       //onmessage拿到返回的心跳就说明连接正常
    14.       console.log("55555");
    15.       ws.send("123456789");
    16.       self.serverTimeoutObj = setTimeout(function() {
    17.         console.log(111);
    18.         console.log(ws);
    19.         ws.close();
    20.         // createWebSocket();
    21.       }, self.timeout);
    22.     }, this.timeout)
    23.   }
    24. }
    复制代码


    实现心跳检测的思路是:每隔一段固定的时间,向服务器端发送一个ping数据,如果在正常的情况下,服务器会返回一个pong给客户端,如果客户端通过
    onmessage事件能监听到的话,说明请求正常,这里我们使用了一个定时器,每隔3秒的情况下,如果是网络断开的情况下,在指定的时间内服务器端并没有返回心跳响应消息,因此服务器端断开了,因此这个时候我们使用ws.close关闭连接,在一段时间后(在不同的浏览器下,时间是不一样的,firefox响应更快),
    可以通过 onclose事件监听到。因此在onclose事件内,我们可以调用 reconnect事件进行重连操作。
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-17 21:04 , Processed in 0.429139 second(s), 45 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表