# HTTP 信令处理器 **本文引用的文件** - [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) ## 目录 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 类
client/src/signaling.js"] end subgraph "服务器端" S_Index["应用入口
src/index.ts"] S_Server["Express 服务器
src/server.ts"] S_Router["HTTP 路由
src/signaling.ts"] S_Handler["HTTP 处理器
src/class/httphandler.ts"] S_WS["WebSocket 信令
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 路由
src/signaling.ts" participant Handler as "HTTP 处理器
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["创建会话
createSession()"] CreateSession --> InitMaps["初始化会话映射"] InitMaps --> Maintain["维护会话
更新 lastRequestedTime"] Maintain --> Poll["轮询接口
getAll/getOffer/getAnswer/getCandidate"] Poll --> TimeoutCheck{"是否超时?"} TimeoutCheck --> |是| DeleteSession["删除会话
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 "客户端
client/src/signaling.js" participant Server as "HTTP 服务器
src/server.ts" participant Router as "路由
src/signaling.ts" participant Handler as "处理器
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)