websocket和SSE

3 阅读3分钟
websocket心跳机制

心跳机制是指通过客户端向服务器(或者服务器向客户端)发送周期性的小消息来检测连接状态、防止连接因超时被关闭,以及维持连接活跃。

let socket = null;
let isConnected = false; // 连接状态标识
let heartbeatInterval = null; // 心跳发送定时器
let timeoutTimer = null; // 超时检测定时器

// 重连尝试的间隔延迟,单位:毫秒
const RECONNECT_DELAY = 5000;
const HEARTBEAT_INTERVAL = 10000; // 心跳间隔时间,单位:毫秒
const TIMEOUT = 15000; // 超时时间,大于心跳间隔时间

function connectWebSocket() {
    // 创建 WebSocket 连接
    socket = new WebSocket('ws://localhost:8080');

    // 连接成功事件
    socket.onopen = () => {
        console.log('WebSocket connection is open.');
        isConnected = true;

        // 启动心跳机制
        startHeartbeat();
    };

    // 处理接收到的消息
    socket.onmessage = (event) => {
        console.log('Message from server:', event.data);

        if (event.data === 'pong') {
            console.log('Received pong from server, connection is alive.');
            // 如果收到服务器 pong,没有超时,清除超时检测定时器
            resetTimeout();
        }
    };

    // 处理连接关闭事件
    socket.onclose = () => {
        console.log('WebSocket connection closed. Retrying...');
        clearHeartbeat(); // 停止心跳机制
        isConnected = false;
        // 尝试重连
        setTimeout(connectWebSocket, RECONNECT_DELAY);
    };

    // 处理错误
    socket.onerror = (error) => {
        console.error('WebSocket encountered error:', error.message);
        // 如果出错,关闭当前连接并尝试重连
        socket.close();
    };
}

// 心跳机制的启动
function startHeartbeat() {
    if (heartbeatInterval) return; // 防止重复启动心跳

    // 定期发送心跳 "ping" 消息
    heartbeatInterval = setInterval(() => {
        if (isConnected && socket.readyState === WebSocket.OPEN) {
            console.log('Sending ping to server...');
            socket.send('ping');
        }
        // 启动超时检测:等待服务器返回响应(pong)
        startTimeout();
    }, HEARTBEAT_INTERVAL);
}

// 启动超时检测
function startTimeout() {
    clearTimeout(timeoutTimer); // 确保定时器不会重复堆叠
    timeoutTimer = setTimeout(() => {
        console.error('No response from server. Closing connection...');
        if (socket.readyState === WebSocket.OPEN) {
            socket.close(); // 主动关闭连接
        }
    }, TIMEOUT);
}

// 超时检测重置
function resetTimeout() {
    clearTimeout(timeoutTimer); // 收到服务器响应后,清除当前超时定时器
}

// 停止心跳机制
function clearHeartbeat() {
    clearInterval(heartbeatInterval);
    clearTimeout(timeoutTimer);
    heartbeatInterval = null;
    timeoutTimer = null;
}

// 初始化 WebSocket 连接
connectWebSocket();
SSE

Server-Sent Events(简称 SSE)是一种浏览器原生支持的服务端推送技术。它允许服务端向浏览器单向发送实时更新数据,而客户端通过一个简单的 HTTP 长连接接收数据。SSE 是基于 HTTP 协议的,支持文本流传输,非常适合实时更新、实时通知等场景。

SSE 是一种轻量级的实时通信技术,与 WebSocket 相比,它只支持服务端到客户端的单向通信。它最初被提出用于 HTML5 标准,部分浏览器原生支持 SSE。

Server-Sent Events 的工作原理

客户端建立连接:
客户端通过 JavaScript 使用 EventSource 对象向服务器发起 HTTP 请求,服务端以流的形式持续发送事件数据。

保持长连接:
连接建立后,客户端保持和服务端的长连接,服务器不断向客户端推送事件。

自动重连:
如果连接断开(例如网络问题或服务端无法响应),客户端会自动尝试重新连接。

特点Server-Sent Events (SSE)WebSocket
通信方式单向(服务端到客户端)双向(双向实时通信)
协议基于 HTTP/1.x独立的 WebSocket 协议
浏览器支持广泛支持较广泛支持
数据格式纯文本文本和二进制数据
使用复杂度简单更复杂,需要服务端支持
连接方式使用 HTTP 长连接单独的 WebSocket 协议连接