====测试代码:

==index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Document</title>
  6. </head>
  7. <body>
  8. <div>
  9. abc
  10. </div>
  11. </body>
  12. <script type="text/javascript" src="js/websocket.js"></script>
  13. <script src="js/client.js"></script>
  14. </html>

==websocket.js

  1. var lockReconnect = false; //避免ws重复连接
  2. var ws = null; // 判断当前浏览器是否支持WebSocket
  3. var wsUrl = null;
  4. var config = {};
  5.  
  6. function socketLink(set) {
  7. config = set;
  8. wsUrl = config.url;
  9. createWebSocket(wsUrl); //连接ws
  10. }
  11.  
  12. function createWebSocket(url) {
  13. try {
  14. if ('WebSocket' in window) {
  15. ws = new WebSocket(url, 'echo-protocol');
  16. } else if ('MozWebSocket' in window) {
  17. ws = new MozWebSocket(url, 'echo-protocol');
  18. } else {
  19. alert("您的浏览器不支持websocket")
  20. }
  21. initEventHandle();
  22. } catch (e) {
  23. reconnect(url);
  24. console.log(e);
  25. }
  26. }
  27.  
  28. function initEventHandle() {
  29. ws.onclose = function() {
  30. reconnect(wsUrl);
  31. console.log("llws连接关闭!" + new Date().toUTCString());
  32. };
  33. ws.onerror = function() {
  34. reconnect(wsUrl);
  35. console.log("llws连接错误!");
  36. };
  37. ws.onopen = function() {
  38. heartCheck.reset().start(); //心跳检测重置
  39. console.log("llws连接成功!" + new Date().toUTCString());
  40. config.open(ws)
  41. };
  42. ws.onmessage = function(event) { //如果获取到消息,心跳检测重置
  43. heartCheck.reset().start(); //拿到任何消息都说明当前连接是正常的
  44. config.msg(event.data,ws)
  45. };
  46. }
  47. // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
  48. window.onbeforeunload = function() {
  49. ws.close();
  50. }
  51.  
  52. function reconnect(url) {
  53. if (lockReconnect) return;
  54. lockReconnect = true;
  55. setTimeout(function() { //没连接上会一直重连,设置延迟避免请求过多
  56. createWebSocket(url);
  57. lockReconnect = false;
  58. }, 2000);
  59. }
  60.  
  61. //心跳检测
  62. var heartCheck = {
  63. timeout: 10000, //9分钟发一次心跳
  64. timeoutObj: null,
  65. serverTimeoutObj: null,
  66. reset: function() {
  67. clearTimeout(this.timeoutObj);
  68. clearTimeout(this.serverTimeoutObj);
  69. return this;
  70. },
  71. start: function() {
  72. var self = this;
  73. this.timeoutObj = setTimeout(function() {
  74. //这里发送一个心跳,后端收到后,返回一个心跳消息,
  75. //onmessage拿到返回的心跳就说明连接正常
  76. ws.send("ping");
  77. console.log("ping!")
  78. self.serverTimeoutObj = setTimeout(function() { //如果超过一定时间还没重置,说明后端主动断开了
  79. console.log("try=close")
  80. ws.close(); //这里为什么要在send检测消息后,倒计时执行这个代码呢,因为这个代码的目的时为了触发onclose方法,这样才能实现onclose里面的重连方法
              //所以这个代码也很重要,没有这个方法,有些时候发了定时检测消息给后端,后端超时(我们自己设定的时间)后,不会自动触发onclose方法。我们只有执行ws.close()代码,让ws触发onclose方法
              //的执行。如果没有这个代码,连接没有断线的情况下而后端没有正常检测响应,那么浏览器时不会自动超时关闭的(比如谷歌浏览器),谷歌浏览器会自动触发onclose
              //是在断网的情况下,在没有断线的情况下,也就是后端响应不正常的情况下,浏览器不会自动触发onclose,所以需要我们自己设定超时自动触发onclose,这也是这个代码的
              //的作用。
  81. }, self.timeout)
  82. }, this.timeout)
  83. }
  84. }

心跳检测的目的时什么呢?

一个是为了定时发送消息,使连接不超时自动断线,可能后端设了超时时间就会自动断线,所以需要定时发送消息给后端,让后端服务器知道连接还在通消息不能断。

二来是为了检测在正常还连接着的情况下,判断后端是否正常,如果我们发了一个定时检测给后端,后端按照约定要下发一个检测消息给前端,这样才是正常的。

可是如果后端没有正常下发呢,我们就要设定一下超时要重连了,我们把重连写在了onclose里面,当时正常连接的情况下,超时未能响应检测消息的情况下,浏览器不会自动断掉触发onclose,所以需要我们手动触发,也就是在超时里写一个ws.close()让ws关闭触发onclose方法,实现重连。

==浏览器会触发onclose的情况是断网断线的情况下,当时正常连接还未断线,浏览器时不会自动触发onclose的,所以就有超时手动触发onclose的必要。

  1. self.serverTimeoutObj = setTimeout(function() { //如果超过一定时间还没重置,说明后端主动断开了
  2. console.log("try=close")
  3. ws.close(); //这里为什么要在send检测消息后,倒计时执行这个代码呢,因为这个代码的目的时为了触发onclose方法,这样才能实现onclose里面的重连方法
  4.           //所以这个代码也很重要,没有这个方法,有些时候发了定时检测消息给后端,后端超时(我们自己设定的时间)后,不会自动触发onclose方法。我们只有执行ws.close()代码,让ws触发onclose方法
  5.           //的执行。如果没有这个代码,连接没有断线的情况下而后端没有正常检测响应,那么浏览器时不会自动超时关闭的(比如谷歌浏览器),谷歌浏览器会自动触发onclose
  6.           //是在断网的情况下,在没有断线的情况下,也就是后端响应不正常的情况下,浏览器不会自动触发onclose,所以需要我们自己设定超时自动触发onclose,这也是这个代码的
  7.           //的作用。
  8.  
  9. }, self.timeout)
  1. ws.onopen = function() {
  2. heartCheck.reset().start(); //心跳检测重置 在open的时候触发心跳检测
  3. console.log("llws连接成功!" + new Date().toUTCString());
  4. config.open(ws)
  5. };
  6. ws.onmessage = function(event) { //如果获取到消息,心跳检测重置
  7. heartCheck.reset().start(); //拿到任何消息都说明当前连接是正常的 //如果后端有下发消息,那么就会重置初始化心跳检测,除非超时没下发,那么就会触发onclose
           //然后触发重连
  8. config.msg(event.data,ws)
  9. };

==client.js

  1. var number=0;
  2. var config = {
  3. url: 'ws://localhost:8080/',
  4. open: (ws) => {
  5. function sendNumber() {
  6. if (ws.readyState === ws.OPEN) {
  7. number = number+1;
  8. ws.send(number.toString());
  9. setTimeout(sendNumber, 1000);
  10. }
  11. }
  12. sendNumber()
  13. },
  14. msg: (data) => {
  15. console.log(data, "msg")
  16. }
  17. }
  18. socketLink(config)

==node 后端测试代码:

  1. #!/usr/bin/env node
  2.  
  3. var WebSocketServer = require('websocket').server;
  4. var http = require('http');
  5.  
  6. var server = http.createServer(function(request, response) {
  7. console.log((new Date()) + ' Received request for ' + request.url);
  8. response.writeHead(404);
  9. response.end();
  10. });
  11. server.listen(8080, function() {
  12. console.log((new Date()) + ' Server is listening on port 8080');
  13. });
  14.  
  15. wsServer = new WebSocketServer({
  16. httpServer: server,
  17. // You should not use autoAcceptConnections for production
  18. // applications, as it defeats all standard cross-origin protection
  19. // facilities built into the protocol and the browser. You should
  20. // *always* verify the connection's origin and decide whether or not
  21. // to accept it.
  22. autoAcceptConnections: false
  23. });
  24.  
  25. function originIsAllowed(origin) {
  26. console.log(origin,"origin")
  27. // put logic here to detect whether the specified origin is allowed.
  28. return true;
  29. }
  30.  
  31. wsServer.on('request', function(request) {
  32. if (!originIsAllowed(request.origin)) {
  33. // Make sure we only accept requests from an allowed origin
  34. request.reject();
  35. console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
  36. return;
  37. }
  38.  
  39. var connection = request.accept('echo-protocol', request.origin);
  40. console.log((new Date()) + ' Connection accepted.');
  41. connection.on('message', function(message) {
  42. if (message.type === 'utf8') {
  43. console.log('Received Message: ' + message.utf8Data);
  44. //connection.sendUTF(message.utf8Data); //注释掉是为了测试前端在没后端响应却连接着的情况下,是什么反应。
  45. } else if (message.type === 'binary') {
  46. console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
  47. connection.sendBytes(message.binaryData);
  48. }
  49. });
  50. connection.on('close', function(reasonCode, description) {
  51. console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
  52. });
  53. });

javascript websocket 心跳检测机制介绍的更多相关文章

  1. netty心跳检测机制

    既然是网络通信那么心跳检测肯定是离不开的,netty心跳检测分为读.写.全局 bootstrap.childHandler(new ChannelInitializer<SocketChanne ...

  2. 面试官:Netty心跳检测机制是什么,怎么自定义检测间隔时间?

    哈喽!大家好,我是小奇,一位热爱分享的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 书接上回,昨天在地里干了一天的 ...

  3. WebSocket心跳检测和重连机制

    1. 心跳重连原由 心跳和重连的目的用一句话概括就是客户端和服务端保证彼此还活着,避免丢包发生. websocket连接断开有以下两证情况: 前端断开 在使用websocket过程中,可能会出现网络断 ...

  4. Netty 中的心跳检测机制

    心跳检测一般存在于建立长连接 或者 需要保活的场景. 心跳的使用场景 长连接的应用场景非常的广泛,比如监控系统,IM系统,即时报价系统,推送服务等等.像这些场景都是比较注重实时性,如果每次发送数据都要 ...

  5. Oracle RAC/Clusterware 多种心跳heartbeat机制介绍 RAC超时机制分析

    ORACLE RAC中最主要存在2种clusterware集群件心跳 &  RAC超时机制分析: 1.Network Heartbeat 网络心跳 每秒发生一次: 10.2.0.4以后网络心跳 ...

  6. 分析dubbo心跳检测机制

    目的: 维持provider和consumer之间的长连接 实现: dubbo心跳时间heartbeat默认是60s,超过heartbeat时间没有收到消息,就发送心跳消息(provider,cons ...

  7. Netty — 心跳检测和断线重连

    一.前言 由于在通信层的网络连接的不可靠性,比如:网络闪断,网络抖动等,经常会出现连接断开.这样对于使用长连接的应用而言,当突然高流量冲击势必会造成进行网络连接,从而产生网络堵塞,应用响应速度下降,延 ...

  8. 理解WebSocket心跳及重连机制(五)

    理解WebSocket心跳及重连机制 在使用websocket的过程中,有时候会遇到网络断开的情况,但是在网络断开的时候服务器端并没有触发onclose的事件.这样会有:服务器会继续向客户端发送多余的 ...

  9. 【Netty】利用Netty实现心跳检测和重连机制

    一.前言 心跳机制是定时发送一个自定义的结构体(心跳包),让对方知道自己还活着,以确保连接的有效性的机制.   我们用到的很多框架都用到了心跳检测,比如服务注册到 Eureka Server 之后会维 ...

随机推荐

  1. 【python全栈开发】初识python

    本人最开始接触python是在2013年接触,写过hello word!在此之前对开发类没有多大兴趣,不知道重要性,属于浑浑噩噩,忙忙乎乎,跌跌撞撞的.随后选择了Linux运维作为就业主攻方向. 经过 ...

  2. Python学习之路基础篇--07Python基础+编码、集合 和 深浅Copy

    1 小数据池(节省内存) 只有数字和字符串中内存,储存在同一个内存地址中 数字的范围在-5~256中,字符串有以下两个特点:不能含有特殊字符,还有就s*20 不是同一个地址,而要*21就不是了 2 编 ...

  3. Unity攻略

    Unity开发VR之Vuforia 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- ...

  4. java将字符串存入oracle的Blob中

    Blob内存放的是字节数组,需使用String的getBytes获得该字符串的字节数组(注意字符集编码),然后存入Blob. Oracle的Blob字段比较特殊,他比long字段的性能要好很多,可以用 ...

  5. php中include和require的区别(整理)

      require 的使用方法如 require("MyRequireFile.php"); .这个函数通常放在 PHP 程序的最前面,PHP 程序在执行前,就会先读入 requi ...

  6. ubuntu18安装navicat

    1.登陆 http://www.navicat.com.cn/download/navicat-for-mysql 页面下载navicat安装包,务必选位置1-64bit ps: 中文版乱码问题严重, ...

  7. mysql Incorrect usage of UNION and ORDER BY 错误备忘

    出现这个错误的语句是酱紫的 select xxx from aaa order by xxx union all select yyy from bbb order by yyy 错误原因居然是,如果 ...

  8. 编程总结5&学习总结

    基础题目 请在第一周作业的基础上,继续完成:找出给定的文件中数组的最大值及其对应的最小下标(下标从0开始).并将最大值和对应的最小下标数值写入文件. 输入:请建立以自己英文名字命名的txt文件,并输入 ...

  9. Django Admin初识

    一.网站后台的作用 网站后台通常是相对于动态网站而言,即网站建设是基于数据库驱动的网站.网站后台,有时也称为网站管理后台,是指用于管理网站前台的一些列操作,如:产品.企业 信息的增加.更新.删除等.通 ...

  10. 《python for data analysis》第七章,数据规整化

    <利用Python进行数据分析>第七章的代码. # -*- coding:utf-8 -*-# <python for data analysis>第七章, 数据规整化 imp ...