websocket檢測伺服器是否斷開-來遊戲手遊解答

語言: CN / TW / HK

為了證明客戶端和伺服器還活著。websocket 在使用過程中,如果遭遇網路問題等,這個時候服務端沒有觸發onclose事件,這樣會產生多餘的連線,並且服務端會繼續傳送訊息給客戶端,造成資料丟失。因此需要一種機制來檢測客戶端和服務端是否處於正常連線的狀態,心跳檢測和重連機制就產生了。

如何進行心跳檢測和遊戲重連

思路是:

每隔一段指定的時間(計時器),向伺服器傳送一個數據,伺服器收到資料後再發送給客戶端,正常情況下客戶端通過onmessage事件是能監聽到伺服器返回的資料的,說明請求正常。

如果再這個指定時間內,客戶端沒有收到伺服器端返回的響應訊息,就判定連線斷開了,使用websocket.close關閉連線。

這個關閉連線的動作可以通過onclose事件監聽到,因此在 onclose 事件內,我們可以呼叫reconnect事件進行重連操作http://www.lyouxi.com。

具體程式碼實現

$(function () {
var path = basePath;

var jspCode = $("#userId").val();

var websocket;

createWebSocket();

/**

* websocket啟動

*/

function createWebSocket() {
try {
if ('WebSocket' in window) {
websocket = new WebSocket((path + "/wsCrm?jspCode=" + jspCode).replace("http", "ws").replace("https", "ws"));

} else if ('MozWebSocket' in window) {
websocket = new MozWebSocket(("ws://" + path + "/wsCrm?jspCode=" + jspCode).replace("http", "ws").replace("https", "ws"));

} else {
websocket = new SockJS(path + "/wsCrm/sockJs?jspCode=" + jspCode.replace("http", "ws"));

}

init();

} catch (e) {
console.log('catch' + e);

reconnect();

}

}

function init() {
//連線成功建立的回撥方法

websocket.onopen = function (event) {
console.log("WebSocket:已連線");

//心跳檢測重置

heartCheck.reset().start();

};

//接收到訊息的回撥方法

websocket.onmessage = function (event) {
showNotify(event.data);

console.log("WebSocket:收到一條訊息", event.data);

heartCheck.reset().start();

};

//連線發生錯誤的回撥方法

websocket.onerror = function (event) {
console.log("WebSocket:發生錯誤");

reconnect();

};

//連線關閉的回撥方法

websocket.onclose = function (event) {
console.log("WebSocket:已關閉");

heartCheck.reset();//心跳檢測

reconnect();

};

//監聽視窗關閉事件,當視窗關閉時,主動去關閉websocket連線,防止連線還沒斷開就關閉視窗,server端會拋異常。

window.onbeforeunload = function () {
websocket.close();

};

//關閉連線

function closeWebSocket() {
websocket.close();

}

//傳送訊息

function send(message) {
websocket.send(message);

}

}

//避免重複連線

var lockReconnect = false, tt;

/**

* websocket重連

*/

function reconnect() {
if (lockReconnect) {
return;

}

lockReconnect = true;

tt && clearTimeout(tt);

tt = setTimeout(function () {
console.log('重連中...');

lockReconnect = false;

createWebSocket();

}, 4000);

}

/**

* websocket心跳檢測

*/

var heartCheck = {
timeout: 5000,

timeoutObj: null,

serverTimeoutObj: null,

reset: function () {
clearTimeout(this.timeoutObj);

clearTimeout(this.serverTimeoutObj);

return this;

},

start: function () {
var self = this;

this.timeoutObj && clearTimeout(this.timeoutObj);

this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);

this.timeoutObj = setTimeout(function () {
//這裡傳送一個心跳,後端收到後,返回一個心跳訊息,

//onmessage拿到返回的心跳就說明連線正常

websocket.send("HeartBeat");

console.log('ping');

self.serverTimeoutObj = setTimeout(function () { // 如果超過一定時間還沒重置,說明後端主動斷開了

console.log('關閉服務');

websocket.close();//如果onclose會執行reconnect,我們執行 websocket.close()就行了.如果直接執行 reconnect 會觸發onclose導致重連兩次

}, self.timeout)

}, this.timeout)

}

};

});