Skip to content

WebSocket 连接与认证

IM 系统使用 WebSocket 实现实时消息通信,支持自动认证和手动认证两种方式。

连接地址

ws://<host>:3000
wss://<host>:3000  (HTTPS 环境下使用)

认证方式

方式一:Query String 自动认证(推荐)

在 WebSocket 连接 URL 中直接携带 JWT token,连接建立后自动完成认证:

javascript
const token = uni.getStorageSync('im_token');
const ws = new WebSocket(`wss://chat.example.com:3000?token=${token}`);

认证成功时服务端推送:

json
{ "type": "auth_success", "data": { "userId": "user_001" } }

认证失败时服务端推送并关闭连接:

json
{ "type": "auth_error", "data": { "message": "令牌无效或已过期" } }

方式二:手动发送认证消息

先建立连接,再发送认证消息:

javascript
const ws = new WebSocket('wss://chat.example.com:3000');

ws.onopen = () => {
  ws.send(JSON.stringify({
    type: 'auth',
    data: { token: 'your-jwt-token' }
  }));
};

心跳机制

客户端与服务端之间通过心跳包维持连接活性。

文本心跳

直接发送纯文本字符串:

javascript
// 客户端发送
ws.send('ping');

// 服务端响应
// 收到纯文本 "pong"

JSON 心跳

通过 JSON 消息格式:

javascript
// 客户端发送
ws.send(JSON.stringify({ type: 'ping' }));

// 服务端响应
// { type: 'pong' }

服务端心跳策略

  • 服务端每 30 秒 向所有客户端发送 ping
  • 如果客户端连续未响应 pong,连接将被终止
  • 建议客户端设置定时器定期发送心跳(如每 25 秒)

重连策略

建议客户端实现指数退避重连:

javascript
let reconnectAttempts = 0;
const maxReconnectDelay = 30000; // 最大 30 秒

function reconnect() {
  reconnectAttempts++;
  const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), maxReconnectDelay);
  
  setTimeout(() => {
    connectWebSocket();
  }, delay);
}

function connectWebSocket() {
  const token = uni.getStorageSync('im_token');
  const ws = new WebSocket(`wss://chat.example.com:3000?token=${token}`);
  
  ws.onopen = () => {
    reconnectAttempts = 0; // 重置重连计数
  };
  
  ws.onclose = () => {
    reconnect();
  };
  
  ws.onerror = () => {
    ws.close();
  };
}

单设备登录(SSO)

当服务端配置 single_sign_on'1' 时,同一用户的新 WebSocket 连接会将旧连接踢下线。

被踢的客户端收到:

json
{
  "type": "kick",
  "data": { "reason": "您的账号在其他设备登录" }
}

WARNING

前端应提示用户并跳转登录页。

速率限制

每个 WebSocket 连接限制为 60 条消息 / 10 秒。超出限制后服务端返回错误:

json
{
  "type": "error",
  "data": { "message": "消息发送过于频繁" }
}

连接生命周期

客户端                          服务端
  │                              │
  │──── WS 连接 ───────────────>│
  │     (携带 token)             │
  │                              │
  │<─── auth_success ───────────│  认证成功
  │                              │
  │──── ping ──────────────────>│  心跳
  │<─── pong ───────────────────│
  │                              │
  │<─── message ────────────────│  收到新消息
  │──── message ───────────────>│  发送消息
  │<─── ack ────────────────────│  发送确认
  │                              │
  │──── ping ──────────────────>│  心跳
  │<─── pong ───────────────────│
  │                              │
  │──── close ─────────────────>│  连接关闭
  │                              │