環境
後臺服務:laravel+swoole
前端:vue+element
使用websocket 的封裝
連接
data(){
return {
lockReconnect: false,
reconnectNum: 0,
ws: "",
}
}
messageSocket(key, message) {
let that = this;
let host = location.host;
let protocol = "ws";
if (location.protocol == "https:") {
protocol = "wss";
}
let ws = new WebSocket(`${protocol}://${host}/ws?key=${key}`);
(this.timeout = 15000), //心跳檢查15秒
ws.onopen = function() {
console.log("ws已連接");
// Web Socket 已連接上,使用 send() 方法發送數據
that.reconnectNum = 0;
sendMessage.send(message);
heartCheck.reset().start();
};
ws.onmessage = function(evt) {
heartCheck.reset().start();
};
ws.onerror = function() {
reconnectSocket.connect();
};
ws.onclose = function(data) {
if (data.code !== 1000) {
reconnectSocket.connect();
}
// 關閉 websocket
console.log("ws連接已關閉...");
};
//數據發送
var sendMessage = {
send(message = "now") {
let sendData = JSON.stringify({
message: message,
interval: that.timeout
});
if (ws.readyState == 1) {
//0 - 表示連接尚未建立;1 - 表示連接已建立,可以進行通信;2 - 表示連接正在進行關閉;3 - 表示連接已經關閉或者連接不能打開
ws.send(sendData);
} else {
console.log("socket連接未建立");
}
}
};
//心跳檢測
var heartCheck = {
timeoutObj: null,
serverTimeoutObj: null,
reset: function() {
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
return this;
},
start: function() {
this.timeoutObj = setTimeout(function() {
//這裏發送一個心跳,後端收到後,返回一個心跳消息,
//onmessage拿到返回的心跳就說明連接正常
sendMessage.send("now");
}, that.timeout);
this.serverTimeoutObj = setTimeout(function() {
//如果超過一定時間還沒重置,說明後端主動斷開了
ws.close(); //如果onclose會執行reconnect,我們執行ws.close()就行了.如果直接執行reconnect 會觸發onclose導致重連兩次
}, that.timeout * 2);
}
};
//斷開重連
var reconnectSocket = {
connect: function() {
if (this.lockReconnect) return;
if (that.reconnectNum >= 4) return;
that.lockReconnect = true;
++that.reconnectNum;
setTimeout(function() {
that.messageSocketValidate();
that.lockReconnect = false;
}, that.timeout);
}
};
},
正常退出
以上代碼封裝,在onClose的時候會自動觸發重連的,所以我們正常退出需要傳入code1000,這樣就不會觸發重連機制
ws.close(1000)
狀態碼的使用
socket的狀態碼我們需要根據下表範圍去選擇
WebSockets 的CloseEvent 會在連接關閉時發送給使用 WebSockets 的客戶端。它在 WebSocket 對象的 onclose 事件監聽器中使用。服務端發送的關閉碼,以下爲已分配的狀態碼。
狀態碼 | 名稱 | 描述 | |
---|---|---|---|
0–999 | - | 保留段, 未使用。 | |
1000 | CLOSE_NORMAL | 正常關閉; 無論爲何目的而創建, 該鏈接都已成功完成任務。 | |
1001 | CLOSE_GOING_AWAY | 終端離開, 可能因爲服務端錯誤, 也可能因爲瀏覽器正從打開連接的頁面跳轉離開。 | |
1002 | CLOSE_PROTOCOL_ERROR | 由於協議錯誤而中斷連接。 | |
1003 | CLOSE_UNSUPPORTED | 由於接收到不允許的數據類型而斷開連接 (如僅接收文本數據的終端接收到了二進制數據)。 | |
1004 | - | 保留。 其意義可能會在未來定義。 | |
1005 | CLOSE_NO_STATUS | 保留。 表示沒有收到預期的狀態碼。 | |
1006 | CLOSE_ABNORMAL | 保留。 用於期望收到狀態碼時連接非正常關閉 (也就是說, 沒有發送關閉幀)。 | |
1007 | Unsupported Data | 由於收到了格式不符的數據而斷開連接 (如文本消息中包含了非 UTF-8 數據)。 | |
1008 | Policy Violation | 由於收到不符合約定的數據而斷開連接。 這是一個通用狀態碼, 用於不適合使用 1003 和 1009 狀態碼的場景。 | |
1009 | CLOSE_TOO_LARGE | 由於收到過大的數據幀而斷開連接。 | |
1010 | Missing Extension | 客戶端期望服務器商定一個或多個拓展, 但服務器沒有處理, 因此客戶端斷開連接。 | |
1011 | Internal Error | 客戶端由於遇到沒有預料的情況阻止其完成請求, 因此服務端斷開連接。 | |
1012 | Service Restart | 服務器由於重啓而斷開連接。 [Ref] | |
1013 | Try Again Later | 服務器由於臨時原因斷開連接, 如服務器過載因此斷開一部分客戶端連接。 [Ref] | |
1014 | - | 由 WebSocket | 標準保留以便未來使用。 |
1015 | TLS Handshake | 保留。 表示連接由於無法完成 TLS 握手而關閉 (例如無法驗證服務器證書)。 | |
1016–1999 | - | 由 WebSocket 標準保留以便未來使用。 | |
2000–2999 | - | 由 WebSocket 拓展保留使用。 | |
3000–3999 | - | 可以由庫或框架使用。 不應由應用使用。 可以在 IANA 註冊, 先到先得。 | |
4000–4999 | - | 可以由應用使用。 |