javascript websocket 心跳檢測機制介紹

來源:互聯網
上載者:User

標籤:doctype   為什麼   utf-8   for   event   catch   超過   測試   protoc   

====測試代碼:

 

==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方法
          //的執行。如果沒有這個代碼,串連沒有斷線的情況下而後端沒有正常檢測響應,那麼瀏覽器時不會自動逾時關閉的(比如Google瀏覽器),Google瀏覽器會自動觸發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方法           //的執行。如果沒有這個代碼,串連沒有斷線的情況下而後端沒有正常檢測響應,那麼瀏覽器時不會自動逾時關閉的(比如Google瀏覽器),Google瀏覽器會自動觸發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.‘);    });});

 

javascript websocket 心跳檢測機制介紹

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.