javascript websocket 心跳检测机制介绍

====测试代码:

==index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div>
        abc
    </div>
</body>
<script type="text/javascript" src="js/websocket.js"></script>
<script src="js/client.js"></script>
</html>

==websocket.js

var lockReconnect = false; //避免ws重复连接
var ws = null; // 判断当前浏览器是否支持WebSocket
var wsUrl = null;
var config = {};

function socketLink(set) {
    config = set;
    wsUrl = config.url;
    createWebSocket(wsUrl); //连接ws
}

function createWebSocket(url) {
    try {
        if (‘WebSocket‘ in window) {
            ws = new WebSocket(url, ‘echo-protocol‘);
        } else if (‘MozWebSocket‘ in window) {
            ws = new MozWebSocket(url, ‘echo-protocol‘);
        } else {
            alert("您的浏览器不支持websocket")
        }
        initEventHandle();
    } catch (e) {
        reconnect(url);
        console.log(e);
    }
}

function initEventHandle() {
    ws.onclose = function() {
        reconnect(wsUrl);
        console.log("llws连接关闭!" + new Date().toUTCString());
    };
    ws.onerror = function() {
        reconnect(wsUrl);
        console.log("llws连接错误!");
    };
    ws.onopen = function() {
        heartCheck.reset().start(); //心跳检测重置
        console.log("llws连接成功!" + new Date().toUTCString());
        config.open(ws)
    };
    ws.onmessage = function(event) { //如果获取到消息,心跳检测重置
        heartCheck.reset().start(); //拿到任何消息都说明当前连接是正常的
        config.msg(event.data,ws)
    };
}
// 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
    ws.close();
}

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

//心跳检测
var heartCheck = {
    timeout: 10000, //9分钟发一次心跳
    timeoutObj: null,
    serverTimeoutObj: null,
    reset: function() {
        clearTimeout(this.timeoutObj);
        clearTimeout(this.serverTimeoutObj);
        return this;
    },
    start: function() {
        var self = this;
        this.timeoutObj = setTimeout(function() {
            //这里发送一个心跳,后端收到后,返回一个心跳消息,
            //onmessage拿到返回的心跳就说明连接正常
            ws.send("ping");
            console.log("ping!")
            self.serverTimeoutObj = setTimeout(function() { //如果超过一定时间还没重置,说明后端主动断开了
                console.log("try=close")
                ws.close(); //这里为什么要在send检测消息后,倒计时执行这个代码呢,因为这个代码的目的时为了触发onclose方法,这样才能实现onclose里面的重连方法          //所以这个代码也很重要,没有这个方法,有些时候发了定时检测消息给后端,后端超时(我们自己设定的时间)后,不会自动触发onclose方法。我们只有执行ws.close()代码,让ws触发onclose方法           //的执行。如果没有这个代码,连接没有断线的情况下而后端没有正常检测响应,那么浏览器时不会自动超时关闭的(比如谷歌浏览器),谷歌浏览器会自动触发onclose          //是在断网的情况下,在没有断线的情况下,也就是后端响应不正常的情况下,浏览器不会自动触发onclose,所以需要我们自己设定超时自动触发onclose,这也是这个代码的          //的作用。
            }, self.timeout)
        }, this.timeout)
    }
}

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

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

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

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

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

self.serverTimeoutObj = setTimeout(function() { //如果超过一定时间还没重置,说明后端主动断开了
                console.log("try=close")
                ws.close(); //这里为什么要在send检测消息后,倒计时执行这个代码呢,因为这个代码的目的时为了触发onclose方法,这样才能实现onclose里面的重连方法
          //所以这个代码也很重要,没有这个方法,有些时候发了定时检测消息给后端,后端超时(我们自己设定的时间)后,不会自动触发onclose方法。我们只有执行ws.close()代码,让ws触发onclose方法
           //的执行。如果没有这个代码,连接没有断线的情况下而后端没有正常检测响应,那么浏览器时不会自动超时关闭的(比如谷歌浏览器),谷歌浏览器会自动触发onclose
          //是在断网的情况下,在没有断线的情况下,也就是后端响应不正常的情况下,浏览器不会自动触发onclose,所以需要我们自己设定超时自动触发onclose,这也是这个代码的
          //的作用。

            }, self.timeout)
ws.onopen = function() {
        heartCheck.reset().start(); //心跳检测重置   在open的时候触发心跳检测
        console.log("llws连接成功!" + new Date().toUTCString());
        config.open(ws)
    };
    ws.onmessage = function(event) { //如果获取到消息,心跳检测重置
        heartCheck.reset().start(); //拿到任何消息都说明当前连接是正常的  //如果后端有下发消息,那么就会重置初始化心跳检测,除非超时没下发,那么就会触发onclose       //然后触发重连
        config.msg(event.data,ws)
    };

==client.js

var number=0;
var config = {
    url: ‘ws://localhost:8080/‘,
    open: (ws) => {
        function sendNumber() {
            if (ws.readyState === ws.OPEN) {
                number = number+1;
                ws.send(number.toString());
                setTimeout(sendNumber, 1000);
            }
        }
        sendNumber()
    },
    msg: (data) => {
        console.log(data, "msg")
    }
}
socketLink(config)

==node 后端测试代码:

#!/usr/bin/env node

var WebSocketServer = require(‘websocket‘).server;
var http = require(‘http‘);

var server = http.createServer(function(request, response) {
    console.log((new Date()) + ‘ Received request for ‘ + request.url);
    response.writeHead(404);
    response.end();
});
server.listen(8080, function() {
    console.log((new Date()) + ‘ Server is listening on port 8080‘);
});

wsServer = new WebSocketServer({
    httpServer: server,
    // You should not use autoAcceptConnections for production
    // applications, as it defeats all standard cross-origin protection
    // facilities built into the protocol and the browser.  You should
    // *always* verify the connection‘s origin and decide whether or not
    // to accept it.
    autoAcceptConnections: false
});

function originIsAllowed(origin) {
    console.log(origin,"origin")
    // put logic here to detect whether the specified origin is allowed.
    return true;
}

wsServer.on(‘request‘, function(request) {
    if (!originIsAllowed(request.origin)) {
        // Make sure we only accept requests from an allowed origin
        request.reject();
        console.log((new Date()) + ‘ Connection from origin ‘ + request.origin + ‘ rejected.‘);
        return;
    }

    var connection = request.accept(‘echo-protocol‘, request.origin);
    console.log((new Date()) + ‘ Connection accepted.‘);
    connection.on(‘message‘, function(message) {
        if (message.type === ‘utf8‘) {
            console.log(‘Received Message: ‘ + message.utf8Data);
            //connection.sendUTF(message.utf8Data);  //注释掉是为了测试前端在没后端响应却连接着的情况下,是什么反应。
        } else if (message.type === ‘binary‘) {
            console.log(‘Received Binary Message of ‘ + message.binaryData.length + ‘ bytes‘);
            connection.sendBytes(message.binaryData);
        }
    });
    connection.on(‘close‘, function(reasonCode, description) {
        console.log((new Date()) + ‘ Peer ‘ + connection.remoteAddress + ‘ disconnected.‘);
    });
});

原文地址:https://www.cnblogs.com/jocongmin/p/9236485.html

时间: 2024-10-10 16:24:58

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

js websocket 心跳检测,断开重连,超时重连

1 function longSock(url, fn, intro = '') { 2 let lockReconnect = false //避免重复连接 3 let timeoutFlag = true 4 let timeoutSet = null 5 let reconectNum = 0 6 const timeout = 30000 //超时重连间隔 7 let ws 8 function reconnect() { 9 if (lockReconnect) return 10 l

使用netty开发心跳检测和重连机制的规划与设计

心跳检测 代码逻辑与设计思路 方案1 1.1心跳机制 通过ping-pong双向心跳机制 可以保证无论通信哪一方出现网络故障,都能被及时检测出来 为了防止由于对方短时间内繁忙没有及时返回应答造成的误判,只有连续N次心跳检测都失败才认定链路已经损害,需要关闭链路并重建链路.当读或者写心跳消息发生I/O异常的时候,说明链路已经中断,此时需要立即关闭链路,如果是客户端,需要重新发起连接.如果是服务端,需要重新发起连接.如果是服务端,需要清空缓存的半包信息,等待客户端重连. 1.2重连机制 如果链路中断

介绍开源的.net通信框架NetworkComms框架之五 心跳检测

原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架  作者是英国人  以前是收费的 目前作者已经开源  许可是:Apache License v2 开源地址是:https://github.com/MarcFletcher/NetworkComms.Net 我们知道TCP连接建立之后,如果没有心跳检测,连接一会就断开了.NetworkComms框架本身已经完美实现了心跳检测,我们在使用的时候不用再关心这个问

websocket-heartbeat-js心跳检测库正式发布

前言: 两年前写了一篇websocket心跳的博客——初探和实现websocket心跳重连.  阅读量一直比较大,加上最近考虑写一个自己的npm包,因此就完成了一个websocket心跳的检测库.在这里先感谢几个提供帮助的大佬朋友们,小弟受益匪浅. 介绍 websocket-heartbeat-js基于浏览器js原生websocket封装,主要目的是保障客户端websocket与服务端连接状态.该程序有心跳检测及自动重连机制,当网络断开或者后端服务问题造成客户端websocket断开,程序会自动

初探和实现websocket心跳重连

心跳重连缘由 在使用websocket过程中,可能会出现网络断开的情况,比如信号不好,或者网络临时性关闭,这时候websocket的连接已经断开, 而浏览器不会执行websocket 的 onclose方法,我们无法知道是否断开连接,也就无法进行重连操作. 如果当前发送websocket数据到后端,一旦请求超时,onclose便会执行,这时候便可进行绑定好的重连操作. 因此websocket心跳重连就应运而生. 如何实现 在websocket实例化的时候,我们会绑定一些事件: var ws =

心跳包机制整理汇总

[背景] 现需要实现这样的功能:有多个客户端连着同一个服务器.服务器和客户端之间需要“互相”知道彼此的连接状态.比如在某一时刻,服务器需要知道当前有多少个客户端正在和其通信:某一个时刻,某个客户端需要知道自己是否和服务器保持连接.如果在某一时刻,一个客户端关闭了,服务端应能及时感觉到:同样,如果服务端被关闭,所有的客户端应能及时感觉到,并作出一些反应. 1.从程序的角度看待TCP掉线 TCP掉线的原因可能多种多样.不一而足,比如,客人的电脑突然断电.OS崩溃.路由器重启.网线接触不良.因为P2P

心跳包机制原理

心跳包的发送,通常有两种技术 方法1:应用层自己实现的心跳包 由应用程序自己发送心跳包来检测连接是否正常,大致的方法是:服务器在一个 Timer事件中定时 向客户端发送一个短小精悍的数据包,然后启动一个低级别的线程,在该线程中不断检测客户端的回应, 如果在一定时间内没有收到客户端的回应,即认为客户端已经掉线:同样,如果客户端在一定时间内没 有收到服务器的心跳包,则认为连接不可用. 方法2:TCP的KeepAlive保活机制 因为要考虑到一个服务器通常会连接多个客户端,因此由用户在应用层自己实现心

Socket心跳包机制

Socket心跳包机制 分类: C++ MFC/C#/Qt TCP/IP/UDP等网络编程2012-12-10 20:42 20431人阅读 评论(4) 收藏 举报 心跳包的发送,通常有两种技术方法1:应用层自己实现的心跳包 由应用程序自己发送心跳包来检测连接是否正常,大致的方法是:服务器在一个 Timer事件中定时 向客户端发送一个短小精悍的数据包,然后启动一个低级别的线程,在该线程中不断检测客户端的回应, 如果在一定时间内没有收到客户端的回应,即认为客户端已经掉线:同样,如果客户端在一定时间

Netty实现服务端客户端长连接通讯及心跳检测

通过netty实现服务端与客户端的长连接通讯,及心跳检测.        基本思路:netty服务端通过一个Map保存所有连接上来的客户端SocketChannel,客户端的Id作为Map的key.每次服务器端如果要向某个客户端发送消息,只需根据ClientId取出对应的SocketChannel,往里面写入message即可.心跳检测通过IdleEvent 事件,定时向服务端放送Ping消息,检测SocketChannel是否终断.         环境JDK1.8 和netty5