# WebSocket 服务器

<cite>
**本文引用的文件**
- [src/index.ts](file://src/index.ts)
- [src/server.ts](file://src/server.ts)
- [src/websocket.ts](file://src/websocket.ts)
- [src/class/websockethandler.ts](file://src/class/websockethandler.ts)
- [src/class/offer.ts](file://src/class/offer.ts)
- [src/class/answer.ts](file://src/class/answer.ts)
- [src/class/candidate.ts](file://src/class/candidate.ts)
- [src/log.ts](file://src/log.ts)
- [src/signaling.ts](file://src/signaling.ts)
- [src/swagger.ts](file://src/swagger.ts)
- [client/src/signaling.js](file://client/src/signaling.js)
- [package.json](file://package.json)
- [test/websockethandler.test.ts](file://test/websockethandler.test.ts)
</cite>

## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)

## 简介
本技术文档围绕 WebSocket 服务器模块进行深入解析，重点覆盖以下方面：
- WebSocket 服务器的创建与配置（含 HTTPS/WSS、日志与启动流程）
- 连接生命周期管理（连接建立、断开、广播、消息路由）
- WSSignaling 类的职责与实现要点（事件监听、消息分发、心跳与超时）
- WebSocketHandler 的核心能力（连接组模型、1对多/多对多路由、广播机制）
- 连接调试与监控方法（日志级别、Swagger 文档、心跳检测）
- 连接池管理、心跳检测与断线重连策略

## 项目结构
后端采用 Express 提供 HTTP/HTTPS 服务与静态资源，WebSocket 信令在独立模块中运行；同时保留 HTTP 轮询信令作为备选方案。

```mermaid
graph TB
subgraph "服务端进程"
A["Express 应用<br/>src/server.ts"]
B["HTTP(S) 服务器<br/>src/index.ts"]
C["WebSocket 信令服务器<br/>src/websocket.ts"]
D["WebSocket 处理器<br/>src/class/websockethandler.ts"]
E["HTTP 信令路由<br/>src/signaling.ts"]
F["Swagger 文档<br/>src/swagger.ts"]
end
subgraph "客户端"
G["浏览器/前端页面<br/>client/public"]
H["信令客户端封装<br/>client/src/signaling.js"]
end
H --> |"WebSocket"| C
H --> |"HTTP 轮询"| E
B --> |"创建/绑定"| C
A --> |"挂载路由/静态资源"| G
A --> |"注册 HTTP 信令路由"| E
A --> |"初始化 Swagger"| F
```

图表来源
- [src/index.ts:52-91](file://src/index.ts#L52-L91)
- [src/server.ts:14-42](file://src/server.ts#L14-L42)
- [src/websocket.ts:15-116](file://src/websocket.ts#L15-L116)
- [src/signaling.ts:4-24](file://src/signaling.ts#L4-L24)
- [src/swagger.ts:16-65](file://src/swagger.ts#L16-L65)

章节来源
- [src/index.ts:13-109](file://src/index.ts#L13-L109)
- [src/server.ts:14-90](file://src/server.ts#L14-L90)
- [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118)
- [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25)
- [src/swagger.ts:16-65](file://src/swagger.ts#L16-L65)

## 核心组件
- WSSignaling：WebSocket 信令服务器入口，负责监听连接、消息解析与分发至 WebSocketHandler。
- WebSocketHandler：核心业务逻辑，维护连接组、1对多/多对多路由、广播、心跳与断线清理。
- 数据模型：Offer、Answer、Candidate 用于封装信令数据。
- 日志系统：统一日志级别控制与输出格式。
- HTTP 信令路由：保留 HTTP 轮询信令通道，便于兼容与调试。
- Swagger 文档：自动生成 API 文档，支持会话认证与信令接口说明。

章节来源
- [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118)
- [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479)
- [src/class/offer.ts:1-11](file://src/class/offer.ts#L1-L11)
- [src/class/answer.ts:1-8](file://src/class/answer.ts#L1-L8)
- [src/class/candidate.ts:1-12](file://src/class/candidate.ts#L1-L12)
- [src/log.ts:1-51](file://src/log.ts#L1-L51)
- [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25)
- [src/swagger.ts:16-65](file://src/swagger.ts#L16-L65)

## 架构总览
WebSocket 服务器在 HTTP(S) 之上提供实时信令通道，客户端可通过 WebSocket 或 HTTP 轮询两种方式接入。WebSocket 信令以“连接组”为核心组织多端通信，支持广播与定向转发。

```mermaid
sequenceDiagram
participant Client as "客户端<br/>client/src/signaling.js"
participant WS as "WSSignaling<br/>src/websocket.ts"
participant Handler as "WebSocketHandler<br/>src/class/websockethandler.ts"
Client->>WS : "WebSocket 连接建立"
WS->>Handler : "add(ws)"
WS-->>Client : "connect 消息role/polite/participantId"
Client->>WS : "发送信令消息offer/answer/candidate/on-message/broadcast"
WS->>Handler : "根据消息类型分发"
Handler-->>Client : "转发/广播结果含 participantId"
Client-->>WS : "断开连接/心跳 ping/pong"
WS->>Handler : "remove(ws)/心跳检测"
```

图表来源
- [src/websocket.ts:27-116](file://src/websocket.ts#L27-L116)
- [src/class/websockethandler.ts:72-137](file://src/class/websockethandler.ts#L72-L137)
- [src/class/websockethandler.ts:404-430](file://src/class/websockethandler.ts#L404-L430)
- [client/src/signaling.js:152-292](file://client/src/signaling.js#L152-L292)

## 详细组件分析

### WSSignaling 类
职责与行为：
- 接收 HTTP 服务器实例，创建 ws.Server 并绑定到同一端口。
- 注册 connection 事件：为新连接调用处理器 add，并在关闭时 remove。
- 注册 message 事件：解析 JSON 消息，按 type 分发到对应处理器（connect/disconnect/offer/answer/candidate/ping/pong/broadcast/on-message/call-request）。
- 内置 ping/pong 心跳：收到 ping 回复 pong，收到 pong 更新 lastActivity；注释掉的心跳定时器可在需要时启用。

实现要点：
- 模式切换：通过 reset(mode) 设置 isPrivate，影响连接组与路由行为。
- 消息格式：支持 participantId 字段以区分多参与者场景。
- 日志：统一通过 log 输出接收到的消息与关键事件。

章节来源
- [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118)
- [src/class/websockethandler.ts:63-66](file://src/class/websockethandler.ts#L63-L66)

### WebSocketHandler 核心功能
- 连接组模型：Map<string, ConnectionGroup>，每个连接组包含 host 与多个 participants。
- 连接管理：add/remove 维护 clients 映射与连接组；onConnect/onDisconnect 实现 1对多/多对多角色分配。
- 信令路由：
  - offer/answer/candidate：host 与 participants 之间双向转发；私有模式下支持按 participantId 精确路由。
  - broadcast：支持全局广播与按连接组广播。
  - on-message：支持聊天消息等扩展消息的组内转发。
- 心跳与超时：提供心跳初始化/清理函数，注释掉的定时器默认不启用；可按需开启。
- 辅助能力：获取所有连接组 ID、判断是否 host、组内广播工具。

```mermaid
classDiagram
class WSSignaling {
+server
+wss
+constructor(server, mode)
}
class WebSocketHandler {
+reset(mode)
+add(ws)
+remove(ws)
+onConnect(ws, connectionId)
+onDisconnect(ws, connectionId)
+onOffer(ws, message)
+onAnswer(ws, message)
+onCandidate(ws, message)
+onBroadcast(ws, message)
+onMessage(ws, message)
+AddHeartbeat(ws, connectionId)
+RemoveHeartbeat(ws)
+isHost(ws, connectionId)
+broadcastToGroup(connectionId, senderWs, message)
}
WSSignaling --> WebSocketHandler : "消息分发"
```

图表来源
- [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118)
- [src/class/websockethandler.ts:63-479](file://src/class/websockethandler.ts#L63-L479)

章节来源
- [src/class/websockethandler.ts:139-206](file://src/class/websockethandler.ts#L139-L206)
- [src/class/websockethandler.ts:208-338](file://src/class/websockethandler.ts#L208-L338)
- [src/class/websockethandler.ts:340-402](file://src/class/websockethandler.ts#L340-L402)
- [src/class/websockethandler.ts:404-430](file://src/class/websockethandler.ts#L404-L430)

### 数据模型
- Offer：封装 SDP、时间戳与是否“polite”标记。
- Answer：封装 SDP 与时间戳。
- Candidate：封装 ICE 候选项与 SDP 元信息及时间戳。

章节来源
- [src/class/offer.ts:1-11](file://src/class/offer.ts#L1-L11)
- [src/class/answer.ts:1-8](file://src/class/answer.ts#L1-L8)
- [src/class/candidate.ts:1-12](file://src/class/candidate.ts#L1-L12)

### 启动与配置
- 命令行参数：端口、HTTPS 开关与证书、信令类型（websocket/http）、通信模式（public/private）、日志级别。
- HTTPS：当 secure=true 时使用 server.key/server.cert 创建 https.Server。
- 信令类型：type=websocket 时启动 WSSignaling；否则提示并回退为 websocket。
- 日志：统一通过 log 模块输出启动信息与运行日志。

章节来源
- [src/index.ts:14-109](file://src/index.ts#L14-L109)
- [src/log.ts:1-51](file://src/log.ts#L1-L51)

### HTTP 信令与 Swagger
- HTTP 信令路由：提供会话管理与信令 CRUD 接口，支持会话认证（session-id）。
- Swagger：自动扫描 httphandler.ts 与 signaling.ts，生成 API 文档，支持会话认证与信令接口说明。

章节来源
- [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25)
- [src/class/httphandler.ts:1112-1130](file://src/class/httphandler.ts#L1112-L1130)
- [src/swagger.ts:16-65](file://src/swagger.ts#L16-L65)

## 依赖关系分析
- 运行时依赖：ws（WebSocket）、express（HTTP）、morgan（日志）、swagger-ui-express（文档）、uuid（会话 ID）。
- 构建与测试：TypeScript、Jest、ESLint、ts-jest 等。
- 客户端：浏览器通过 WebSocket 或 HTTP 轮询与服务端交互。

```mermaid
graph LR
P["package.json 依赖声明"] --> WS["ws"]
P --> EXP["express"]
P --> MORGAN["morgan"]
P --> SWG["swagger-ui-express"]
P --> UUID["uuid"]
IDX["src/index.ts"] --> SRV["src/server.ts"]
IDX --> WSC["src/websocket.ts"]
WSC --> WSH["src/class/websockethandler.ts"]
SRV --> SIG["src/signaling.ts"]
SRV --> SWG
```

图表来源
- [package.json:14-46](file://package.json#L14-L46)
- [src/index.ts:7-11](file://src/index.ts#L7-L11)
- [src/server.ts:5-9](file://src/server.ts#L5-L9)
- [src/websocket.ts:1-4](file://src/websocket.ts#L1-L4)
- [src/class/websockethandler.ts:5-8](file://src/class/websockethandler.ts#L5-L8)
- [src/signaling.ts:1-3](file://src/signaling.ts#L1-L3)
- [src/swagger.ts:5-9](file://src/swagger.ts#L5-L9)

章节来源
- [package.json:14-60](file://package.json#L14-L60)
- [src/index.ts:7-11](file://src/index.ts#L7-L11)
- [src/server.ts:5-9](file://src/server.ts#L5-L9)
- [src/websocket.ts:1-4](file://src/websocket.ts#L1-L4)
- [src/class/websockethandler.ts:5-8](file://src/class/websockethandler.ts#L5-L8)
- [src/signaling.ts:1-3](file://src/signaling.ts#L1-L3)
- [src/swagger.ts:5-9](file://src/swagger.ts#L5-L9)

## 性能考量
- 连接组规模：每组 participants 使用 Set 存储，查找与删除均为 O(1)，适合中小规模并发。
- 广播策略：组内广播遍历 participants，建议限制单组成员数量或引入分区策略。
- 心跳检测：当前注释掉定时器，避免不必要的 CPU 占用；如启用需合理设置周期与超时阈值。
- 日志级别：生产环境建议提升日志级别，减少高频日志输出对性能的影响。
- HTTPS 证书：WSS 需要正确配置证书与密钥，确保握手与传输安全。

## 故障排查指南
- 启动与网络
  - 确认端口占用与防火墙放行。
  - HTTPS 模式检查 server.key 与 server.cert 是否存在且可读。
- WebSocket 连接
  - 检查客户端 WebSocket URL（ws/wss）与主机一致。
  - 观察浏览器开发者工具 Network 面板中的 WebSocket 握手与帧。
- 信令消息
  - 使用 Swagger 文档校验 HTTP 信令接口（PUT/GET/POST/DELETE）参数与会话 ID。
  - 对照客户端 signaling.js 的消息构造与事件派发。
- 日志定位
  - 调整日志级别（info/warn/error/log），关注连接建立、断开、广播与路由关键节点。
- 自动化测试
  - 参考单元测试用例，验证 public/private 模式下的连接、offer/answer/candidate 转发与广播行为。

章节来源
- [src/index.ts:55-88](file://src/index.ts#L55-L88)
- [src/log.ts:11-51](file://src/log.ts#L11-L51)
- [src/swagger.ts:16-65](file://src/swagger.ts#L16-L65)
- [client/src/signaling.js:152-292](file://client/src/signaling.js#L152-L292)
- [test/websockethandler.test.ts:1-191](file://test/websockethandler.test.ts#L1-L191)

## 结论
该 WebSocket 服务器模块以简洁清晰的职责划分实现了 WebRTC 信令的核心需求：支持 WebSocket 与 HTTP 两种信令通道、基于连接组的 1对多/多对多路由、广播与定向转发、以及可扩展的消息类型。通过日志与 Swagger 的配合，具备良好的可观测性与可维护性。建议在高并发场景下进一步优化广播与心跳策略，并完善断线重连与幂等处理。

## 附录

### WebSocket 连接调试与监控
- 浏览器开发者工具：Network 面板查看握手、帧与错误。
- Swagger 文档：访问 /api-docs，使用 session-id 头部进行认证，查看 HTTP 信令接口。
- 日志：通过命令行参数设置日志级别，观察连接、断开、广播与路由事件。
- 心跳：若启用心跳定时器，注意 ping/pong 的周期与超时阈值配置。

章节来源
- [src/swagger.ts:16-65](file://src/swagger.ts#L16-L65)
- [src/log.ts:11-51](file://src/log.ts#L11-L51)
- [src/class/websockethandler.ts:404-430](file://src/class/websockethandler.ts#L404-L430)

### 连接池管理、心跳检测与断线重连
- 连接池管理：clients 与 connectionGroup 维护连接映射与组关系，remove 时清理并广播断开事件。
- 心跳检测：提供 AddHeartbeat/RemoveHeartbeat，当前代码注释掉定时器；可按需启用。
- 断线重连：客户端应实现指数退避与自动重连逻辑；服务端在断开时通知组内成员并清理资源。

章节来源
- [src/class/websockethandler.ts:115-137](file://src/class/websockethandler.ts#L115-L137)
- [src/class/websockethandler.ts:404-430](file://src/class/websockethandler.ts#L404-L430)
- [client/src/signaling.js:230-241](file://client/src/signaling.js#L230-L241)