# 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、type（websocket/http）、mode（public/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)