This commit is contained in:
2026-05-16 13:24:02 +08:00
parent eae60714b4
commit 6c13817527
42 changed files with 15921 additions and 0 deletions

View File

@@ -0,0 +1,379 @@
# HTTP 信令处理器
<cite>
**本文引用的文件**
- [src/class/httphandler.ts](file://src/class/httphandler.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/signaling.ts](file://src/signaling.ts)
- [src/server.ts](file://src/server.ts)
- [src/index.ts](file://src/index.ts)
- [client/src/signaling.js](file://client/src/signaling.js)
- [test/httphandler.test.ts](file://test/httphandler.test.ts)
- [src/log.ts](file://src/log.ts)
- [src/class/options.ts](file://src/class/options.ts)
- [src/websocket.ts](file://src/websocket.ts)
- [src/class/websockethandler.ts](file://src/class/websockethandler.ts)
- [src/服务端接口与WebSocket消息类型.md](file://src/服务端接口与WebSocket消息类型.md)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构概览](#架构概览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件为 HTTP 信令处理器的综合技术文档,重点阐述基于 HTTP 轮询的信令工作机制与实现细节。HTTP 信令通过一组 RESTful 接口实现会话管理、消息缓存与检索、以及客户端轮询拉取等核心能力。文档同时提供与 WebSocket 信令的对比分析,涵盖适用场景、性能特点、错误处理、超时管理与重试机制,并给出实际使用示例与最佳实践建议。
## 项目结构
该项目采用前后端分离的模块化组织方式HTTP 信令相关的核心代码位于以下位置:
- 服务器端核心处理器src/class/httphandler.ts
- 信令路由定义src/signaling.ts
- 服务器创建与中间件配置src/server.ts
- 应用入口与协议选择src/index.ts
- 客户端 HTTP 信令实现client/src/signaling.js
- 测试用例test/httphandler.test.ts
- 日志与配置src/log.ts、src/class/options.ts
- WebSocket 对比实现src/websocket.ts、src/class/websockethandler.ts
```mermaid
graph TB
subgraph "客户端"
C_Signaling["Signaling 类<br/>client/src/signaling.js"]
end
subgraph "服务器端"
S_Index["应用入口<br/>src/index.ts"]
S_Server["Express 服务器<br/>src/server.ts"]
S_Router["HTTP 路由<br/>src/signaling.ts"]
S_Handler["HTTP 处理器<br/>src/class/httphandler.ts"]
S_WS["WebSocket 信令<br/>src/websocket.ts"]
end
C_Signaling --> |"HTTP 轮询"| S_Router
S_Router --> S_Handler
S_Index --> S_Server
S_Server --> S_Router
S_Index --> S_WS
```
**图表来源**
- [src/index.ts:52-91](file://src/index.ts#L52-L91)
- [src/server.ts:14-42](file://src/server.ts#L14-L42)
- [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25)
- [src/class/httphandler.ts:1112-1130](file://src/class/httphandler.ts#L1112-L1130)
- [client/src/signaling.js:30-91](file://client/src/signaling.js#L30-L91)
**章节来源**
- [src/index.ts:13-109](file://src/index.ts#L13-L109)
- [src/server.ts:14-90](file://src/server.ts#L14-L90)
- [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25)
## 核心组件
- HTTP 信令处理器:负责会话管理、消息缓存与检索、连接配对、超时清理等核心逻辑。
- 数据模型类Offer、Answer、Candidate封装信令消息的数据结构。
- HTTP 路由层:定义 /signaling 下的 REST 接口,统一鉴权中间件与会话校验。
- 客户端轮询实现:基于 Fetch API 的轮询机制,按 fromtime 实现增量拉取。
- 测试框架:覆盖公共/私有模式下的会话生命周期、消息传递与超时清理。
**章节来源**
- [src/class/httphandler.ts:31-120](file://src/class/httphandler.ts#L31-L120)
- [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/signaling.ts:6-24](file://src/signaling.ts#L6-L24)
- [client/src/signaling.js:30-91](file://client/src/signaling.js#L30-L91)
- [test/httphandler.test.ts:6-310](file://test/httphandler.test.ts#L6-L310)
## 架构概览
HTTP 信令的整体架构围绕“会话-连接-消息”三层结构展开:
- 会话Session通过 PUT /signaling 创建,携带 Session-Id 头进行后续请求鉴权。
- 连接Connection在会话内创建/删除,用于标识对端参与者。
- 消息Offer/Answer/Candidate在连接之间传递按 fromtime 实现增量拉取。
```mermaid
sequenceDiagram
participant Client as "客户端"
participant Router as "HTTP 路由<br/>src/signaling.ts"
participant Handler as "HTTP 处理器<br/>src/class/httphandler.ts"
Client->>Router : "PUT /signaling"
Router->>Handler : "createSession()"
Handler-->>Router : "{ sessionId }"
Router-->>Client : "返回 sessionId"
Client->>Router : "PUT /signaling/connection"
Router->>Handler : "createConnection()"
Handler-->>Router : "{ connectionId, polite }"
Router-->>Client : "返回连接信息"
Client->>Router : "GET /signaling?fromtime=..."
Router->>Handler : "getAll()/getOffer()/getAnswer()/getCandidate()"
Handler-->>Router : "合并后的消息数组"
Router-->>Client : "返回增量消息"
Client->>Router : "POST /signaling/offer|answer|candidate"
Router->>Handler : "postOffer()/postAnswer()/postCandidate()"
Handler-->>Router : "200 OK"
Router-->>Client : "确认接收"
```
**图表来源**
- [src/signaling.ts:15-22](file://src/signaling.ts#L15-L22)
- [src/class/httphandler.ts:664-675](file://src/class/httphandler.ts#L664-L675)
- [src/class/httphandler.ts:739-783](file://src/class/httphandler.ts#L739-L783)
- [src/class/httphandler.ts:615-641](file://src/class/httphandler.ts#L615-L641)
- [src/class/httphandler.ts:855-886](file://src/class/httphandler.ts#L855-L886)
- [src/class/httphandler.ts:913-952](file://src/class/httphandler.ts#L913-L952)
- [src/class/httphandler.ts:985-998](file://src/class/httphandler.ts#L985-L998)
## 详细组件分析
### 会话管理策略
- 会话创建:调用 createSession() 生成唯一 sessionId并初始化会话级映射连接集合、Offer/Answer/Candidate 缓存、断开连接记录)。
- 会话维护checkSessionId() 中更新 lastRequestedTime作为超时判断依据轮询接口 getAll()/getOffer()/getAnswer()/getCandidate() 均先触发超时检查。
- 会话销毁deleteSession() 删除会话及其所有连接_deleteConnection() 同步清理连接对、消息缓存与断开记录。
```mermaid
flowchart TD
Start(["开始"]) --> CreateSession["创建会话<br/>createSession()"]
CreateSession --> InitMaps["初始化会话映射"]
InitMaps --> Maintain["维护会话<br/>更新 lastRequestedTime"]
Maintain --> Poll["轮询接口<br/>getAll/getOffer/getAnswer/getCandidate"]
Poll --> TimeoutCheck{"是否超时?"}
TimeoutCheck --> |是| DeleteSession["删除会话<br/>deleteSession()"]
TimeoutCheck --> |否| Continue["继续处理"]
DeleteSession --> End(["结束"])
Continue --> End
```
**图表来源**
- [src/class/httphandler.ts:664-675](file://src/class/httphandler.ts#L664-L675)
- [src/class/httphandler.ts:128-145](file://src/class/httphandler.ts#L128-L145)
- [src/class/httphandler.ts:218-232](file://src/class/httphandler.ts#L218-L232)
- [src/class/httphandler.ts:697-696](file://src/class/httphandler.ts#L697-L696)
- [src/class/httphandler.ts:153-194](file://src/class/httphandler.ts#L153-L194)
**章节来源**
- [src/class/httphandler.ts:128-145](file://src/class/httphandler.ts#L128-L145)
- [src/class/httphandler.ts:218-232](file://src/class/httphandler.ts#L218-L232)
- [src/class/httphandler.ts:697-696](file://src/class/httphandler.ts#L697-L696)
- [src/class/httphandler.ts:153-194](file://src/class/httphandler.ts#L153-L194)
### 消息缓存机制
- Offer 缓存:以 sessionId -> connectionId -> Offer 映射存储,支持按 fromtime 过滤与跨会话(公共模式)广播。
- Answer 缓存:以 sessionId -> connectionId -> Answer 映射存储,公共模式下向配对会话广播。
- Candidate 缓存:以 sessionId -> connectionId -> Candidate[] 数组存储,按 fromtime 过滤Answer 到来时同步更新对应 Candidate 的时间戳。
- 断开连接记录:以 sessionId -> Disconnection[] 数组存储,支持按 fromtime 过滤。
```mermaid
classDiagram
class Offer {
+string sdp
+number datetime
+boolean polite
}
class Answer {
+string sdp
+number datetime
}
class Candidate {
+string candidate
+number sdpMLineIndex
+string sdpMid
+number datetime
}
class Disconnection {
+string id
+number datetime
}
class HTTPHandler {
+Map~string,Set~string~~ clients
+Map~string,number~ lastRequestedTime
+Map~string,Map~string,Offer~~ offers
+Map~string,Map~string,Answer~~ answers
+Map~string,Map~string,Candidate[]~~ candidates
+Map~string,Disconnection[]~~ disconnections
+Map~string,[string,string]~ connectionPair
}
HTTPHandler --> Offer : "缓存"
HTTPHandler --> Answer : "缓存"
HTTPHandler --> Candidate : "缓存"
HTTPHandler --> Disconnection : "记录"
```
**图表来源**
- [src/class/httphandler.ts:42-84](file://src/class/httphandler.ts#L42-L84)
- [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/class/httphandler.ts:58-84](file://src/class/httphandler.ts#L58-L84)
- [src/class/httphandler.ts:268-356](file://src/class/httphandler.ts#L268-L356)
- [src/class/httphandler.ts:941-951](file://src/class/httphandler.ts#L941-L951)
### 轮询接口设计与实现
- GET /signaling合并连接、断开、Offer、Answer、Candidate 消息,按 datetime 升序返回;支持 fromtime 过滤。
- GET /signaling/offer|answer|candidate分别返回对应类型消息支持 fromtime 过滤。
- GET /signaling/connection返回当前会话的连接列表。
- PUT /signaling创建会话返回 sessionId。
- DELETE /signaling删除会话。
- PUT|DELETE /signaling/connection创建/删除连接。
- POST /signaling/offer|answer|candidate提交信令消息。
客户端轮询流程:
- 首次启动PUT /signaling 获取 sessionId随后循环调用 GET /signaling 并解析消息类型分派事件。
- 增量拉取:使用上次响应中的 datetime 作为 fromtime避免重复接收历史消息。
```mermaid
sequenceDiagram
participant Client as "客户端<br/>client/src/signaling.js"
participant Server as "HTTP 服务器<br/>src/server.ts"
participant Router as "路由<br/>src/signaling.ts"
participant Handler as "处理器<br/>src/class/httphandler.ts"
Client->>Server : "PUT /signaling"
Server->>Router : "转发请求"
Router->>Handler : "createSession()"
Handler-->>Router : "{ sessionId }"
Router-->>Client : "返回 sessionId"
loop 轮询
Client->>Server : "GET /signaling?fromtime=..."
Server->>Router : "转发请求"
Router->>Handler : "getAll()"
Handler-->>Router : "messages + datetime"
Router-->>Client : "返回增量消息"
end
```
**图表来源**
- [src/server.ts:25-26](file://src/server.ts#L25-L26)
- [src/signaling.ts:15-16](file://src/signaling.ts#L15-L16)
- [src/class/httphandler.ts:615-641](file://src/class/httphandler.ts#L615-L641)
- [client/src/signaling.js:30-91](file://client/src/signaling.js#L30-L91)
**章节来源**
- [src/signaling.ts:9-22](file://src/signaling.ts#L9-L22)
- [src/class/httphandler.ts:398-407](file://src/class/httphandler.ts#L398-L407)
- [src/class/httphandler.ts:440-447](file://src/class/httphandler.ts#L440-L447)
- [src/class/httphandler.ts:492-501](file://src/class/httphandler.ts#L492-L501)
- [src/class/httphandler.ts:549-558](file://src/class/httphandler.ts#L549-L558)
- [src/class/httphandler.ts:615-641](file://src/class/httphandler.ts#L615-L641)
- [client/src/signaling.js:147-149](file://client/src/signaling.js#L147-L149)
### 与 WebSocket 信令的对比分析
- 适用场景
- HTTP 轮询适合受限网络环境NAT/防火墙)、代理服务器较多、无法建立长连接的场景。
- WebSocket适合实时性要求高、连接稳定、浏览器/移动端原生支持良好的场景。
- 性能特点
- HTTP 轮询:每次请求均为独立 TCP 连接,存在额外握手开销;但可利用 HTTP 缓存与代理优化。
- WebSocket单连接复用无握手开销延迟更低带宽利用率更高。
- 一致性与复杂度
- HTTP 轮询:需自行实现 fromtime 增量拉取与会话超时管理。
- WebSocket内置连接状态管理消息有序到达无需显式超时处理。
**章节来源**
- [src/服务端接口与WebSocket消息类型.md:533-542](file://src/服务端接口与WebSocket消息类型.md#L533-L542)
- [src/websocket.ts:15-39](file://src/websocket.ts#L15-L39)
- [src/class/websockethandler.ts](file://src/class/websockethandler.ts)
### 错误处理、超时管理与重试机制
- 会话超时:默认 10 秒未请求则自动清理会话;通过 _checkForTimedOutSessions() 触发。
- 连接冲突:私有模式下同一 connectionId 仅允许一次配对,重复使用返回 400。
- 请求校验checkSessionId() 未找到会话返回 404缺少必要字段返回 400。
- 客户端重试:客户端轮询间隔默认 1 秒,若未获取到 sessionId 会持续重试直至成功。
```mermaid
flowchart TD
A["收到请求"] --> B{"会话存在?"}
B --> |否| E["返回 404"]
B --> |是| C["更新 lastRequestedTime"]
C --> D{"是否超时?"}
D --> |是| F["清理会话并返回空消息"]
D --> |否| G["继续处理请求"]
```
**图表来源**
- [src/class/httphandler.ts:128-145](file://src/class/httphandler.ts#L128-L145)
- [src/class/httphandler.ts:218-232](file://src/class/httphandler.ts#L218-L232)
- [test/httphandler.test.ts:29-33](file://test/httphandler.test.ts#L29-L33)
**章节来源**
- [src/class/httphandler.ts:31-32](file://src/class/httphandler.ts#L31-L32)
- [src/class/httphandler.ts:218-232](file://src/class/httphandler.ts#L218-L232)
- [test/httphandler.test.ts:29-33](file://test/httphandler.test.ts#L29-L33)
- [test/httphandler.test.ts:363-379](file://test/httphandler.test.ts#L363-L379)
### 实际使用示例与最佳实践
- 客户端使用步骤
- 初始化 Signaling 实例,设置轮询间隔。
- 调用 start() 自动创建会话并进入轮询循环。
- 监听 disconnect/offer/answer/candidate 事件处理信令。
- 使用 createConnection()/deleteConnection() 管理连接。
- 使用 sendOffer()/sendAnswer()/sendCandidate() 发送信令。
- 最佳实践
- 合理设置轮询间隔(如 1-2 秒),平衡实时性与资源消耗。
- 使用 fromtime 实现增量拉取,避免重复处理历史消息。
- 在私有模式下确保 connectionId 的唯一性,避免 400 错误。
- 在受限网络环境下优先选择 HTTP 轮询,否则推荐 WebSocket。
**章节来源**
- [client/src/signaling.js:30-91](file://client/src/signaling.js#L30-L91)
- [client/src/signaling.js:99-138](file://client/src/signaling.js#L99-L138)
- [test/httphandler.test.ts:35-153](file://test/httphandler.test.ts#L35-L153)
## 依赖关系分析
- 服务器启动与协议选择index.ts 根据配置决定启用 HTTP 轮询还是 WebSocket。
- 服务器中间件server.ts 配置 CORS、JSON 解析、静态资源与 Swagger 文档。
- 路由与处理器signaling.ts 注册 HTTP 路由并挂载会话校验中间件,具体逻辑由 httphandler.ts 实现。
- 客户端依赖client/src/signaling.js 通过 Fetch API 与服务器交互。
```mermaid
graph LR
Index["src/index.ts"] --> Server["src/server.ts"]
Server --> Router["src/signaling.ts"]
Router --> Handler["src/class/httphandler.ts"]
Client["client/src/signaling.js"] --> Router
```
**图表来源**
- [src/index.ts:75-88](file://src/index.ts#L75-L88)
- [src/server.ts:25-41](file://src/server.ts#L25-L41)
- [src/signaling.ts:9-22](file://src/signaling.ts#L9-L22)
**章节来源**
- [src/index.ts:52-91](file://src/index.ts#L52-L91)
- [src/server.ts:14-90](file://src/server.ts#L14-L90)
- [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25)
## 性能考虑
- 轮询频率:过高的轮询频率会增加服务器负载与网络开销;建议根据业务场景调整至 1-3 秒。
- fromtime 增量拉取:减少不必要的数据传输,降低带宽占用。
- 超时清理:及时释放闲置会话资源,避免内存泄漏。
- 缓存策略:合理控制消息缓存大小,避免长时间运行导致内存增长。
## 故障排除指南
- 404 会话不存在:确认客户端已成功创建会话并正确携带 Session-Id 头。
- 400 连接 ID 冲突:私有模式下同一 connectionId 已被使用,需更换或释放。
- 超时被清理:若长时间无请求,会话会被自动清理;可通过定期轮询维持会话活性。
- 增量消息缺失:检查 fromtime 参数是否正确传递,避免重复消费历史消息。
**章节来源**
- [src/class/httphandler.ts:128-145](file://src/class/httphandler.ts#L128-L145)
- [src/class/httphandler.ts:153-194](file://src/class/httphandler.ts#L153-L194)
- [test/httphandler.test.ts:29-33](file://test/httphandler.test.ts#L29-L33)
- [test/httphandler.test.ts:363-379](file://test/httphandler.test.ts#L363-L379)
## 结论
HTTP 信令处理器通过简洁的 REST 接口实现了完整的会话管理与消息缓存能力,结合客户端轮询机制满足了在受限网络环境下的信令需求。其与 WebSocket 的对比显示了在不同场景下的取舍WebSocket 更适合高实时性与高并发场景,而 HTTP 轮询则具备更好的兼容性与部署灵活性。配合 fromtime 增量拉取、超时清理与错误处理机制HTTP 信令可在多数实际应用中稳定运行。
## 附录
- 配置项说明secure、port、keyfile、certfile、typewebsocket/http、modepublic/private、logging。
- 日志级别none/error/warn/log/info默认 info。
**章节来源**
- [src/class/options.ts:1-10](file://src/class/options.ts#L1-L10)
- [src/log.ts:1-51](file://src/log.ts#L1-L51)
- [src/index.ts:20-41](file://src/index.ts#L20-L41)