Files
2026-05-16 13:24:02 +08:00

305 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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)
## 核心组件
- WSSignalingWebSocket 信令服务器入口,负责监听连接、消息解析与分发至 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/candidatehost 与 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)
## 依赖关系分析
- 运行时依赖wsWebSocket、expressHTTP、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 URLws/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)