无码国模产在线观看免费-无码国内精品久久人妻-无码国内精品久久综合88-无码国内精品人妻少妇-无码国内精品人妻少妇蜜桃视频-无码国语中文在线播放

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網站管理員

【WEB開發(fā)】websocket心跳保持連接機制

admin
2025年3月31日 18:17 本文熱度 441

心跳機制在 WebSocket 通信中是一種常用的技術,用于維持連接的穩(wěn)定性、檢測連接是否正常。以下為你詳細介紹在前端使用 WebSocket 時如何實現(xiàn)心跳機制,以及相關代碼示例。

實現(xiàn)思路

  • 發(fā)送心跳包:客戶端定期向服務器發(fā)送一個特定格式的消息(心跳包),以表明自己處于活躍狀態(tài)。
  • 接收響應:服務器收到心跳包后,返回一個響應消息,客戶端通過檢查是否收到響應來判斷連接是否正常。
  • 超時處理:如果客戶端在一定時間內沒有收到服務器的響應,認為連接可能出現(xiàn)問題,嘗試重新連接。

示例代碼

class WebSocketClient {
    constructor(url) {
        this.url = url;
        this.socket = null;
        this.reconnectInterval = 5000; // 重連間隔時間,單位:毫秒
        this.reconnectTimer = null;
        this.messageHandlers = [];
        this.errorHandlers = [];
        this.openHandlers = [];
        this.closeHandlers = [];

        this.heartbeatInterval = 3000; // 心跳間隔時間,單位:毫秒
        this.heartbeatTimer = null;
        this.lastHeartbeatResponseTime = null;
        this.heartbeatTimeout = 5000; // 心跳超時時間,單位:毫秒
        this.heartbeatTimeoutTimer = null;

        this.tryConnect();
    }

    // 嘗試建立連接
    tryConnect() {
        this.socket = new WebSocket(this.url);

        this.socket.onopen = () => {
            console.log('WebSocket 連接已建立');
            clearInterval(this.reconnectTimer);
            this.openHandlers.forEach(handler => handler());
            this.startHeartbeat();
        };

        this.socket.onmessage = (event) => {
            if (event.data === 'heartbeat_response') {
                this.lastHeartbeatResponseTime = Date.now();
                clearTimeout(this.heartbeatTimeoutTimer);
                this.heartbeatTimeoutTimer = setTimeout(() => {
                    this.handleHeartbeatTimeout();
                }, this.heartbeatTimeout);
            } else {
                this.messageHandlers.forEach(handler => handler(event.data));
            }
        };

        this.socket.onerror = (error) => {
            console.error('WebSocket 連接出錯:', error);
            this.errorHandlers.forEach(handler => handler(error));
            this.reconnect();
        };

        this.socket.onclose = (event) => {
            console.log('WebSocket 連接已關閉,代碼:', event.code, '原因:', event.reason);
            this.closeHandlers.forEach(handler => handler(event));
            this.reconnect();
            this.stopHeartbeat();
        };
    }

    // 重連機制
    reconnect() {
        if (!this.reconnectTimer) {
            this.reconnectTimer = setInterval(() => {
                console.log('嘗試重新連接 WebSocket...');
                this.tryConnect();
            }, this.reconnectInterval);
        }
    }

    // 發(fā)送消息
    sendMessage(message) {
        if (this.socket && this.socket.readyState === WebSocket.OPEN) {
            this.socket.send(message);
        } else {
            console.error('無法發(fā)送消息,WebSocket 未連接');
        }
    }

    // 添加消息處理函數
    onMessage(handler) {
        this.messageHandlers.push(handler);
    }

    // 添加錯誤處理函數
    onError(handler) {
        this.errorHandlers.push(handler);
    }

    // 添加連接打開處理函數
    onOpen(handler) {
        this.openHandlers.push(handler);
    }

    // 添加連接關閉處理函數
    onClose(handler) {
        this.closeHandlers.push(handler);
    }

    // 關閉連接
    close() {
        if (this.socket) {
            clearInterval(this.reconnectTimer);
            this.socket.close();
            this.stopHeartbeat();
        }
    }

    // 啟動心跳機制
    startHeartbeat() {
        this.heartbeatTimer = setInterval(() => {
            this.sendMessage('heartbeat');
            this.heartbeatTimeoutTimer = setTimeout(() => {
                this.handleHeartbeatTimeout();
            }, this.heartbeatTimeout);
        }, this.heartbeatInterval);
    }

    // 停止心跳機制
    stopHeartbeat() {
        clearInterval(this.heartbeatTimer);
        clearTimeout(this.heartbeatTimeoutTimer);
    }

    // 處理心跳超時
    handleHeartbeatTimeout() {
        console.log('心跳超時,嘗試重新連接...');
        this.socket.close();
    }
}

// 使用示例
const socketClient = new WebSocketClient('ws://echo.websocket.org');

// 監(jiān)聽消息
socketClient.onMessage((message) => {
    console.log('收到消息:', message);
});

// 監(jiān)聽連接打開
socketClient.onOpen(() => {
    console.log('連接已打開');
});

// 監(jiān)聽錯誤
socketClient.onError((error) => {
    console.error('發(fā)生錯誤:', error);
});

// 監(jiān)聽連接關閉
socketClient.onClose((event) => {
    console.log('連接關閉:', event);
});

代碼解釋

  1. 構造函數:除了初始化基本的 WebSocket 連接參數外,還初始化了心跳機制相關的參數,如心跳間隔時間 heartbeatInterval、心跳超時時間 heartbeatTimeout 等。
  2. startHeartbeat 方法:使用 setInterval 定時發(fā)送心跳包(heartbeat),并啟動一個定時器 heartbeatTimeoutTimer 用于檢測心跳超時。
  3. onmessage 事件處理:當收到服務器的心跳響應消息(heartbeat_response)時,更新最后一次收到響應的時間 lastHeartbeatResponseTime,并重置心跳超時定時器。
  4. handleHeartbeatTimeout 方法:當心跳超時發(fā)生時,關閉當前的 WebSocket 連接,觸發(fā)重連機制。
  5. stopHeartbeat 方法:停止心跳定時器和超時定時器。

通過上述代碼,你可以在前端 WebSocket 通信中實現(xiàn)一個簡單的心跳機制,確保連接的穩(wěn)定性。同時,服務器端也需要相應地處理心跳包并返回響應消息。

分享

用ping\pong來實現(xiàn)

在 WebSocket 通信里,ping 和 pong 是標準的心跳機制實現(xiàn)方式。ping 是客戶端或服務器發(fā)送的探測消息,pong 則是對 ping 的響應。下面是一個使用 JavaScript 封裝 WebSocket 并利用 ping/pong 實現(xiàn)心跳機制的詳細示例。

實現(xiàn)思路

  • 客戶端:周期性地發(fā)送 ping 消息,同時監(jiān)聽 pong 響應,若超時未收到 pong 則認為連接異常。
  • 服務器端:接收到 ping 消息后,立即返回 pong 響應。

前端代碼示例

class WebSocketWithPingPong {
    constructor(url) {
        this.url = url;
        this.socket = null;
        this.pingInterval = 5000; // 發(fā)送 ping 消息的間隔時間(毫秒)
        this.pongTimeout = 3000; // 等待 pong 響應的超時時間(毫秒)
        this.pingTimer = null;
        this.pongTimeoutTimer = null;
        this.reconnectInterval = 5000; // 重連間隔時間(毫秒)
        this.reconnectTimer = null;
        this.messageHandlers = [];
        this.errorHandlers = [];
        this.openHandlers = [];
        this.closeHandlers = [];

        this.connect();
    }

    connect() {
        this.socket = new WebSocket(this.url);

        this.socket.onopen = () => {
            console.log('WebSocket 連接已建立');
            clearInterval(this.reconnectTimer);
            this.openHandlers.forEach(handler => handler());
            this.startPing();
        };

        this.socket.onmessage = (event) => {
            if (event.data === 'pong') {
                clearTimeout(this.pongTimeoutTimer);
            } else {
                this.messageHandlers.forEach(handler => handler(event.data));
            }
        };

        this.socket.onerror = (error) => {
            console.error('WebSocket 連接出錯:', error);
            this.errorHandlers.forEach(handler => handler(error));
            this.reconnect();
        };

        this.socket.onclose = (event) => {
            console.log('WebSocket 連接已關閉,代碼:', event.code, '原因:', event.reason);
            this.closeHandlers.forEach(handler => handler(event));
            this.reconnect();
            this.stopPing();
        };
    }

    reconnect() {
        if (!this.reconnectTimer) {
            this.reconnectTimer = setInterval(() => {
                console.log('嘗試重新連接 WebSocket...');
                this.connect();
            }, this.reconnectInterval);
        }
    }

    sendMessage(message) {
        if (this.socket && this.socket.readyState === WebSocket.OPEN) {
            this.socket.send(message);
        } else {
            console.error('無法發(fā)送消息,WebSocket 未連接');
        }
    }

    onMessage(handler) {
        this.messageHandlers.push(handler);
    }

    onError(handler) {
        this.errorHandlers.push(handler);
    }

    onOpen(handler) {
        this.openHandlers.push(handler);
    }

    onClose(handler) {
        this.closeHandlers.push(handler);
    }

    close() {
        if (this.socket) {
            clearInterval(this.reconnectTimer);
            this.socket.close();
            this.stopPing();
        }
    }

    startPing() {
        this.pingTimer = setInterval(() => {
            this.sendMessage('ping');
            this.pongTimeoutTimer = setTimeout(() => {
                this.handlePongTimeout();
            }, this.pongTimeout);
        }, this.pingInterval);
    }

    stopPing() {
        clearInterval(this.pingTimer);
        clearTimeout(this.pongTimeoutTimer);
    }

    handlePongTimeout() {
        console.log('未收到 pong 響應,嘗試重新連接...');
        this.socket.close();
    }
}

// 使用示例
const socket = new WebSocketWithPingPong('ws://your-websocket-server-url');

socket.onOpen(() => {
    console.log('連接已打開');
});

socket.onMessage((message) => {
    console.log('收到消息:', message);
});

socket.onError((error) => {
    console.error('發(fā)生錯誤:', error);
});

socket.onClose((event) => {
    console.log('連接關閉:', event);
});

代碼解釋

  1. 構造函數:初始化 WebSocket 連接所需的參數,包括 ping 發(fā)送間隔、pong 超時時間、重連間隔等,并且調用 connect 方法開始建立連接。
  2. connect 方法:創(chuàng)建 WebSocket 實例,為 onopenonmessageonerror 和 onclose 事件綁定處理函數。連接建立成功后,啟動 ping 發(fā)送機制。
  3. startPing 方法:使用 setInterval 周期性地發(fā)送 ping 消息,同時啟動一個 pong 超時定時器。
  4. onmessage 事件處理:當收到 pong 響應時,清除 pong 超時定時器;若收到其他消息,則調用注冊的消息處理函數。
  5. handlePongTimeout 方法:若在 pong 超時時間內未收到 pong 響應,關閉當前連接并觸發(fā)重連機制。
  6. 其他方法:如 sendMessage 用于發(fā)送消息,onMessageonErroronOpen 和 onClose 用于注冊相應的事件處理函數,close 用于關閉連接,stopPing 用于停止 ping 發(fā)送和 pong 超時檢測。

服務器端示例(使用 Node.js 和 ws 庫)

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', (ws) => {
    ws.on('message', (message) => {
        if (message === 'ping') {
            ws.send('pong');
        } else {
            // 處理其他消息
            console.log('收到消息:', message);
        }
    });
});

console.log('WebSocket 服務器已啟動,監(jiān)聽端口 8080');

服務器端代碼解釋

  • 使用 ws 庫創(chuàng)建一個 WebSocket 服務器,監(jiān)聽 8080 端口。
  • 當有客戶端連接時,監(jiān)聽 message 事件,若收到 ping 消息,立即返回 pong 響應;若收到其他消息,則進行相應處理。

作者:coding_time
鏈接:https://juejin.cn/post/7475896691884900390
來源:稀土掘金
著作權歸作者所有。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處。

該文章在 2025/4/1 12:59:13 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業(yè)務管理,結合碼頭的業(yè)務特點,圍繞調度、堆場作業(yè)而開發(fā)的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統(tǒng),標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: a级毛片视频在线观看 | 李宗瑞完整版种子 | 久久久久亚洲av无码网站 | 国产精品583一区二区免费看 | 中文字幕乱码熟妇五十中出 | 乱人伦人妻中文字幕 | 99久久精品免费看国产一区二区三区 | 久久久av波多野结衣一区二区 | 专区国产精品第一页 | 日本久久高清一区二区三区毛片 | 日本欧美一区二区三区四区 | 精品日韩二区三区精品视频 | 久久久久无码国产精品一区中 | 国产亚洲欧美日韩在线看片 | 亚洲日本一区二欧美国产亚洲日韩在 | 成人网站免费观看 | 高清一区二区三区日本久 | 人妻仑乱少妇88maⅴ | 韩国精品视频一区二区在线播放 | 久久九九有精品国产23百花影 | 国产亚洲精品久久精品录音 | 久久爱色综合天天综合网 | 日韩爆乳一区二区无码 | 风韵丰满熟妇啪啪区老老熟女百度 | 成人无码精品1区2区 | 国产一级一片免费播放视频 | 欧美亚洲精品中文 | 欧美性精品人妖 | 97人妻久久久精品系列A片 | 精品无码专区亚洲 | 午夜国产视频 | av無碼精品一區二區三區四區 | 午夜中文字幕屏蔽 | 日日干干日日 | 久久精品无码一区二区国产 | 亚洲三级影院 | 国产一区二区日韩专区 | av亚洲欧洲日产国码无码 | 国产精品系列在线一区 | 美女内射无套日韩免费播放 | 国产亚洲欧美日韩综合 |