abc

javascript websocket 心跳检测机制介绍

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; // 判断当前浏览器是否支持WebSocketvar 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 nodevar 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.‘);    });});

免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部