Skip to content

一、WebSocket 核心原理与优势

WebSocket 是一种基于 TCP 的全双工通信协议,通过单次握手建立持久连接,实现客户端与服务端双向实时数据传输。相较于传统 HTTP 轮询,其优势包括:

  • 低延迟:无需重复建立连接,减少握手开销.
  • 高效通信:数据帧头部仅 2~10 字节,传输效率高.
  • 主动推送:服务端可主动向客户端发送数据,无需等待请求.

二、前端实现 WebSocket 的步骤

1. 建立基础连接

javascript
// 客户端连接示例(使用加密协议wss)
const socket = new WebSocket("wss://your-domain.com/ws");

// 事件监听
socket.onopen = () => {
  console.log("连接已建立");
  socket.send(JSON.stringify({ type: "auth", token: "xxx" })); // 发送认证信息
};

socket.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log("收到消息:", data);
};

socket.onerror = (error) => {
  console.error("连接错误:", error);
};

socket.onclose = () => {
  console.log("连接已关闭");
};

2. 服务端实现(Node.js 示例)

javascript
const WebSocket = require("ws");
const wss = new WebSocket.Server({ port: 8080 });

wss.on("connection", (ws) => {
  ws.on("message", (message) => {
    const data = JSON.parse(message);
    // 广播消息给所有客户端
    wss.clients.forEach((client) => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(
          JSON.stringify({ type: "broadcast", content: data.content })
        );
      }
    });
  });
});

三、高级功能实现

1. 心跳机制(保活)

javascript
// 客户端心跳发送
let heartbeatTimer;
socket.onopen = () => {
  heartbeatTimer = setInterval(() => {
    if (socket.readyState === WebSocket.OPEN) {
      socket.send(JSON.stringify({ type: "heartbeat" }));
    }
  }, 30000); // 30秒一次
};

// 服务端检测心跳
ws.on("message", (message) => {
  const data = JSON.parse(message);
  if (data.type === "heartbeat") {
    ws.lastPing = Date.now(); // 记录最新心跳时间
  }
});

// 定时检查未响应连接
setInterval(() => {
  wss.clients.forEach((ws) => {
    if (Date.now() - ws.lastPing > 60000) {
      // 超时60秒断开
      ws.terminate();
    }
  });
}, 5000);

2. 自动重连机制

javascript
class ReconnectableWebSocket {
  constructor(url) {
    this.url = url;
    this.reconnectInterval = 3000; // 3秒重试间隔
    this.connect();
  }

  connect() {
    this.ws = new WebSocket(this.url);
    this.ws.onclose = () => {
      setTimeout(() => this.connect(), this.reconnectInterval);
    };
    // 其他事件绑定...
  }
}

3. 二进制数据传输

javascript
// 发送ArrayBuffer
const buffer = new ArrayBuffer(4);
const view = new DataView(buffer);
view.setUint32(0, 1234);
socket.send(buffer);

// 接收二进制数据
socket.binaryType = "arraybuffer";
socket.onmessage = (event) => {
  if (event.data instanceof ArrayBuffer) {
    const view = new DataView(event.data);
    console.log("收到二进制数据:", view.getInt32(0));
  }
};

四、安全性与跨域处理

    1. 使用 WSS 协议:通过 TLS 加密传输数据,防止中间人攻击。
    1. 验证 Origin 头:服务端需校验请求来源域名,防止 CSRF 攻击。
    1. 限制消息频率:防止客户端恶意发送高频消息。

五、推荐第三方库

    1. Socket.IO:支持自动降级(如轮询)与跨平台。
    1. ws(Node.js):轻量级服务端实现,适合高性能场景。
    1. SockJS:兼容老旧浏览器,提供 WebSocket 模拟。

六、适用场景与最佳实践

  • 实时聊天:消息即时收发,支持群聊/私聊。
  • 金融行情:毫秒级推送股票价格变动。
  • 在线游戏:同步玩家动作与状态。
  • 协同编辑:多人实时修改文档。

实践建议

  • 使用readyState属性管理连接状态(0-连接中,1-已连接,2-关闭中,3-已关闭)。
  • 通过bufferedAmount监控未发送数据量,避免内存溢出。
  • 结合WebWorker处理高频数据,减少主线程阻塞。

通过上述方案,前端项目可高效实现实时通信功能。具体代码示例可参考中的实战案例。