请讲讲WebSocket如何维持连接?

194 阅读2分钟
WebSocket 维持连接的核心机制主要依赖于以下几个关键技术点:

### 1. 握手协议建立连接
WebSocket 通过 HTTP 升级协议建立初始连接:
```javascript
// 客户端发起WebSocket连接
const socket = new WebSocket('ws://example.com/socket');

// 服务端响应(Node.js示例)
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
  console.log('连接已建立');
});

握手过程包含:

  • 客户端发送Upgrade: websocket
  • 服务端响应101 Switching Protocols
  • 交换Sec-WebSocket-Key验证

2. 心跳机制保持活跃

两种常见的心跳实现方式:

方案A:Ping/Pong帧

// 服务端定时发送Ping
setInterval(() => {
  wss.clients.forEach((client) => {
    if (client.readyState === WebSocket.OPEN) {
      client.ping();
    }
  });
}, 30000);

// 客户端响应Pong
socket.on('pong', () => {
  console.log('收到心跳响应');
});

方案B:自定义心跳协议

// 双向心跳检测
let heartbeatInterval;

socket.on('open', () => {
  heartbeatInterval = setInterval(() => {
    socket.send(JSON.stringify({ type: 'heartbeat' }));
  }, 25000);
});

socket.on('message', (data) => {
  if (data.type === 'heartbeat') {
    socket.send(JSON.stringify({ type: 'heartbeat_ack' }));
  }
});

3. 断线重连策略

健壮的重连实现示例:

let reconnectAttempts = 0;
const maxReconnectAttempts = 5;

function connect() {
  const socket = new WebSocket('ws://example.com/socket');
  
  socket.onclose = (e) => {
    if (reconnectAttempts < maxReconnectAttempts) {
      const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), 30000);
      setTimeout(connect, delay);
      reconnectAttempts++;
    }
  };

  socket.onopen = () => {
    reconnectAttempts = 0;
  };
}

4. 流量控制优化

关键优化手段:

  • 使用二进制帧替代文本传输
// 发送ArrayBuffer
const buffer = new ArrayBuffer(128);
socket.send(buffer);

// 接收二进制数据
socket.binaryType = 'arraybuffer';
socket.onmessage = (e) => {
  if (e.data instanceof ArrayBuffer) {
    // 处理二进制数据
  }
};

5. 连接状态监控

完整的连接状态管理:

const connectionMonitor = {
  lastActivity: Date.now(),
  
  start() {
    setInterval(() => {
      if (Date.now() - this.lastActivity > 60000) {
        socket.close();
      }
    }, 10000);
  },
  
  recordActivity() {
    this.lastActivity = Date.now();
  }
};

socket.onmessage = () => connectionMonitor.recordActivity();

最佳实践总结

  1. 始终实现双向心跳检测
  2. 采用指数退避重连策略
  3. 重要操作添加消息确认机制
  4. 生产环境建议使用WSS协议
  5. 考虑使用Socket.io等成熟库处理兼容性问题

完整实现示例:

class RobustWebSocket {
  constructor(url) {
    this.url = url;
    this.reconnectDelay = 1000;
    this.maxReconnectDelay = 30000;
    this.connect();
  }

  connect() {
    this.ws = new WebSocket(this.url);
    
    this.ws.onopen = () => {
      this.startHeartbeat();
      this.reconnectDelay = 1000;
    };

    this.ws.onclose = () => {
      setTimeout(() => this.connect(), 
        Math.min(this.reconnectDelay *= 2, this.maxReconnectDelay));
    };
  }

  startHeartbeat() {
    clearInterval(this.heartbeatInterval);
    this.heartbeatInterval = setInterval(() => {
      if (this.ws.readyState === WebSocket.OPEN) {
        this.ws.send('ping');
      }
    }, 25000);
  }
}