您现在的位置是:网站首页 > WebSocket实现文章详情

WebSocket实现

WebSocket是一种在单个TCP连接上进行全双工通信的协议,适合需要实时交互的应用场景。Node.js通过ws等库提供了完整的WebSocket实现能力,从基础连接到高级功能如心跳检测、广播机制均可覆盖。

WebSocket基础概念

WebSocket协议在HTTP握手后升级为持久化连接,与HTTP请求-响应模式不同,它允许服务端主动推送数据。关键特性包括:

  • 低延迟:建立连接后数据传输无需重复握手
  • 双向通信:客户端和服务端可同时发送消息
  • 轻量级:数据帧头仅2-10字节

协议标识符为ws(非加密)或wss(SSL加密),握手阶段通过HTTP头完成:

GET /chat HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

Node.js服务端实现

使用ws库搭建服务

安装基础依赖:

npm install ws

创建基础服务端:

const WebSocket = require('ws');

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

wss.on('connection', (ws) => {
  console.log('新客户端连接');
  
  ws.on('message', (message) => {
    console.log(`收到消息: ${message}`);
    ws.send(`服务器回应: ${message}`);
  });

  ws.on('close', () => {
    console.log('客户端断开连接');
  });
});

连接生命周期管理

典型事件处理流程:

wss.on('connection', (ws) => {
  // 标识客户端
  ws.id = generateUUID();
  
  // 错误处理
  ws.on('error', (error) => {
    console.error(`客户端 ${ws.id} 错误:`, error);
  });

  // 心跳检测
  const heartbeat = () => {
    ws.isAlive = true;
  };
  
  const interval = setInterval(() => {
    if (!ws.isAlive) return ws.terminate();
    ws.isAlive = false;
    ws.ping();
  }, 30000);

  ws.on('pong', heartbeat);
});

客户端实现示例

浏览器端基础连接:

const socket = new WebSocket('ws://localhost:8080');

socket.addEventListener('open', (event) => {
  socket.send('Hello Server!');
});

socket.addEventListener('message', (event) => {
  console.log('来自服务端的消息:', event.data);
});

// 重连机制
function reconnect() {
  setTimeout(() => {
    new WebSocket(socket.url);
  }, 5000);
}

高级功能实现

广播消息实现

向所有客户端广播消息:

wss.clients.forEach((client) => {
  if (client.readyState === WebSocket.OPEN) {
    client.send(JSON.stringify({
      type: 'broadcast',
      data: '系统公告'
    }));
  }
});

房间分组管理

const rooms = {};

wss.on('connection', (ws) => {
  ws.on('join', (roomId) => {
    if (!rooms[roomId]) rooms[roomId] = new Set();
    rooms[roomId].add(ws);
  });

  ws.on('leave', (roomId) => {
    rooms[roomId]?.delete(ws);
  });
});

function broadcastToRoom(roomId, message) {
  rooms[roomId]?.forEach(client => {
    client.send(message);
  });
}

性能优化实践

消息压缩配置

启用permessage-deflate扩展:

const wss = new WebSocket.Server({
  port: 8080,
  perMessageDeflate: {
    zlibDeflateOptions: {
      chunkSize: 1024,
      memLevel: 7,
      level: 3
    },
    threshold: 1024 // 仅大于1KB的消息压缩
  }
});

连接数限制

防止DDoS攻击:

const wss = new WebSocket.Server({
  maxPayload: 1024 * 1024, // 1MB
  verifyClient: (info, cb) => {
    const isValid = info.origin === 'https://trusted-domain.com';
    cb(isValid);
  }
});

安全防护措施

TLS加密配置

const fs = require('fs');
const server = require('https').createServer({
  cert: fs.readFileSync('server.crt'),
  key: fs.readFileSync('server.key')
});

const wss = new WebSocket.Server({ server });
server.listen(443);

消息验证模式

ws.on('message', (rawData) => {
  try {
    const data = JSON.parse(rawData);
    if (!validateSchema(data)) {
      throw new Error('非法消息格式');
    }
    processMessage(data);
  } catch (err) {
    ws.terminate();
  }
});

调试与问题排查

连接状态监控

setInterval(() => {
  console.log(`当前连接数: ${wss.clients.size}`);
  console.log(`内存使用: ${process.memoryUsage().rss / 1024 / 1024}MB`);
}, 5000);

错误日志记录

wss.on('error', (err) => {
  fs.appendFileSync('websocket.log', 
    `${new Date().toISOString()} - ${err.stack}\n`
  );
});

实际应用场景

实时协作编辑器

操作同步实现片段:

// 客户端发送编辑操作
socket.send(JSON.stringify({
  type: 'text-update',
  position: 42,
  text: '新增内容'
}));

// 服务端处理
ws.on('message', (msg) => {
  const operation = JSON.parse(msg);
  broadcastToRoom(operation.docId, msg);
});

在线游戏状态同步

// 玩家位置更新
setInterval(() => {
  const players = Array.from(wss.clients)
    .map(client => client.playerData);
  
  wss.clients.forEach(client => {
    client.send(JSON.stringify({
      type: 'game-state',
      players
    }));
  });
}, 100);

上一篇: TCP/UDP编程

下一篇: 网络代理实现

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步