Files
video_socket-server/.qoder/repowiki/zh/content/信令系统/信令消息对象.md
2026-05-16 13:24:02 +08:00

396 lines
15 KiB
Markdown
Raw 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.
# 信令消息对象
<cite>
**本文引用的文件**
- [offer.ts](file://src/class/offer.ts)
- [answer.ts](file://src/class/answer.ts)
- [candidate.ts](file://src/class/candidate.ts)
- [httphandler.ts](file://src/class/httphandler.ts)
- [websockethandler.ts](file://src/class/websockethandler.ts)
- [signaling.ts](file://src/signaling.ts)
- [websocket.ts](file://src/websocket.ts)
- [signaling.js](file://client/src/signaling.js)
- [signaling.test.js](file://client/test/signaling.test.js)
- [服务端接口与WebSocket消息类型.md](file://src/服务端接口与WebSocket消息类型.md)
- [package.json](file://package.json)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件系统性地文档化了 WebRTC 信令消息对象 Offer、Answer 和 Candidate 的数据结构、字段定义与实现细节。重点覆盖:
- Offer 类的 SDP 描述封装、时间戳管理与礼貌协商标志polite语义
- Answer 类的应答消息构建与 SDP 交换流程
- Candidate 类的 ICE 候选者序列化与传输机制
- 消息对象的创建、验证与序列化方法
- JSON 结构规范与字段含义
- 实际消息交换示例与调试技巧
- 不同通信模式(公共/私有)下的使用差异
## 项目结构
该项目采用前后端分离的 TypeScript/JavaScript 架构,核心信令逻辑位于服务端的 HTTP 与 WebSocket 处理器中,前端提供基于 HTTP 轮询与 WebSocket 的信令客户端。
```mermaid
graph TB
subgraph "客户端"
FE_HTTP["HTTP 客户端<br/>signaling.js"]
FE_WS["WebSocket 客户端<br/>signaling.js"]
end
subgraph "服务端"
HTTP["HTTP 路由<br/>signaling.ts"]
WS["WebSocket 服务器<br/>websocket.ts"]
HHTTP["HTTP 处理器<br/>httphandler.ts"]
HWS["WebSocket 处理器<br/>websockethandler.ts"]
MODELS["消息模型<br/>offer.ts / answer.ts / candidate.ts"]
end
FE_HTTP --> HTTP
FE_WS --> WS
HTTP --> HHTTP
WS --> HWS
HHTTP --> MODELS
HWS --> MODELS
```
图表来源
- [signaling.ts:1-25](file://src/signaling.ts#L1-L25)
- [websocket.ts:1-118](file://src/websocket.ts#L1-L118)
- [httphandler.ts:1-120](file://src/class/httphandler.ts#L1-L120)
- [websockethandler.ts:1-120](file://src/class/websockethandler.ts#L1-L120)
- [offer.ts:1-11](file://src/class/offer.ts#L1-L11)
- [answer.ts:1-8](file://src/class/answer.ts#L1-L8)
- [candidate.ts:1-12](file://src/class/candidate.ts#L1-L12)
章节来源
- [signaling.ts:1-25](file://src/signaling.ts#L1-L25)
- [websocket.ts:1-118](file://src/websocket.ts#L1-L118)
- [httphandler.ts:1-120](file://src/class/httphandler.ts#L1-L120)
- [websockethandler.ts:1-120](file://src/class/websockethandler.ts#L1-L120)
- [offer.ts:1-11](file://src/class/offer.ts#L1-L11)
- [answer.ts:1-8](file://src/class/answer.ts#L1-L8)
- [candidate.ts:1-12](file://src/class/candidate.ts#L1-L12)
## 核心组件
- Offer封装 SDP 描述、时间戳与礼貌协商标志
- Answer封装 SDP 描述与时间戳
- Candidate封装 ICE 候选者、SDP 媒体行索引与媒体 ID、时间戳
这些类作为纯数据载体,被 HTTP 与 WebSocket 处理器在消息收发时构造与使用。
章节来源
- [offer.ts:1-11](file://src/class/offer.ts#L1-L11)
- [answer.ts:1-8](file://src/class/answer.ts#L1-L8)
- [candidate.ts:1-12](file://src/class/candidate.ts#L1-L12)
## 架构总览
HTTP 与 WebSocket 两条路径共同承载信令消息的收发与存储,处理器负责:
- 会话与连接管理
- 消息持久化与检索
- 消息路由与广播
- 通信模式(公共/私有)下的差异化行为
```mermaid
sequenceDiagram
participant C as "客户端(HTTP)"
participant R as "HTTP 路由(signaling.ts)"
participant H as "HTTP 处理器(httphandler.ts)"
participant S as "存储(Maps)"
participant WS as "WebSocket 服务器(websocket.ts)"
C->>R : POST /signaling/offer
R->>H : postOffer(...)
H->>S : 存储 Offer 对象
H-->>C : 200 OK
C->>R : GET /signaling/offer?fromtime=...
R->>H : getOffer(...)
H->>S : 查询并过滤
H-->>C : {offers : [{connectionId,sdp,polite,type,datetime}]}
Note over WS,H : WebSocket 路由与处理器同样处理 offer/answer/candidate
```
图表来源
- [signaling.ts:20-22](file://src/signaling.ts#L20-L22)
- [httphandler.ts:268-318](file://src/class/httphandler.ts#L268-L318)
- [websocket.ts:44-114](file://src/websocket.ts#L44-L114)
- [websockethandler.ts:214-260](file://src/class/websockethandler.ts#L214-L260)
## 详细组件分析
### Offer 类分析
Offer 类用于封装 WebRTC Offer 信令消息的核心数据,包含 SDP 描述、时间戳与礼貌协商标志。
- 字段定义
- sdp: string —— SDP 描述字符串
- datetime: number —— 消息创建时间戳(毫秒)
- polite: boolean —— 礼貌协商标志,用于避免并发 offer 冲突
- 构造与使用
- HTTP 处理器在收到 offer 后,使用 sdp、当前时间与默认 polite 构造 Offer 对象并持久化
- WebSocket 处理器在收到 offer 后,同样构造 Offer 对象并进行路由
- 礼貌协商Polite语义
- 在私有模式下host 的 polite=falseparticipant 的 polite=true
- 在公共模式下polite 字段通常为 false由服务端统一构造
```mermaid
classDiagram
class Offer {
+string sdp
+number datetime
+boolean polite
+constructor(sdp, datetime, polite)
}
```
图表来源
- [offer.ts:1-11](file://src/class/offer.ts#L1-L11)
- [websockethandler.ts:214-247](file://src/class/websockethandler.ts#L214-L247)
- [httphandler.ts:268-318](file://src/class/httphandler.ts#L268-L318)
章节来源
- [offer.ts:1-11](file://src/class/offer.ts#L1-L11)
- [websockethandler.ts:214-247](file://src/class/websockethandler.ts#L214-L247)
- [httphandler.ts:268-318](file://src/class/httphandler.ts#L268-L318)
### Answer 类分析
Answer 类用于封装 WebRTC Answer 信令消息的核心数据,包含 SDP 描述与时间戳。
- 字段定义
- sdp: string —— SDP 描述字符串
- datetime: number —— 消息创建时间戳(毫秒)
- 构造与使用
- HTTP 处理器在收到 answer 后,使用 sdp、当前时间构造 Answer 对象并持久化
- WebSocket 处理器在收到 answer 后,同样构造 Answer 对象并进行路由
```mermaid
classDiagram
class Answer {
+string sdp
+number datetime
+constructor(sdp, datetime)
}
```
图表来源
- [answer.ts:1-8](file://src/class/answer.ts#L1-L8)
- [websockethandler.ts:268-301](file://src/class/websockethandler.ts#L268-L301)
- [httphandler.ts:300-318](file://src/class/httphandler.ts#L300-L318)
章节来源
- [answer.ts:1-8](file://src/class/answer.ts#L1-L8)
- [websockethandler.ts:268-301](file://src/class/websockethandler.ts#L268-L301)
- [httphandler.ts:300-318](file://src/class/httphandler.ts#L300-L318)
### Candidate 类分析
Candidate 类用于封装 ICE 候选者消息包含候选者字符串、SDP 媒体行索引与媒体 ID、时间戳。
- 字段定义
- candidate: string —— ICE 候选者描述
- sdpMLineIndex: number —— SDP 媒体行索引
- sdpMid: string —— SDP 媒体 ID
- datetime: number —— 消息创建时间戳(毫秒)
- 构造与使用
- HTTP 处理器在收到 candidate 后,使用 candidate、sdpMLineIndex、sdpMid、当前时间构造 Candidate 对象并持久化
- WebSocket 处理器在收到 candidate 后,同样构造 Candidate 对象并进行路由
```mermaid
classDiagram
class Candidate {
+string candidate
+number sdpMLineIndex
+string sdpMid
+number datetime
+constructor(candidate, sdpMLineIndex, sdpMid, datetime)
}
```
图表来源
- [candidate.ts:1-12](file://src/class/candidate.ts#L1-L12)
- [websockethandler.ts:309-338](file://src/class/websockethandler.ts#L309-L338)
- [httphandler.ts:320-356](file://src/class/httphandler.ts#L320-L356)
章节来源
- [candidate.ts:1-12](file://src/class/candidate.ts#L1-L12)
- [websockethandler.ts:309-338](file://src/class/websockethandler.ts#L309-L338)
- [httphandler.ts:320-356](file://src/class/httphandler.ts#L320-L356)
### 消息对象的创建、验证与序列化
- 创建
- HTTP客户端通过 POST /signaling/offer、/answer、/candidate 发送 JSON服务端在处理器中解析并构造对应消息对象
- WebSocket客户端通过发送包含 type 与 data 的 JSON服务端在 WebSocket 处理器中解析并构造对应消息对象
- 验证
- HTTP处理器对必要字段进行校验如 connectionId、sdp、candidate 等),并在缺失时返回错误
- WebSocket处理器对消息结构进行校验确保 from、to、data 字段存在
- 序列化
- HTTP消息对象被转换为 JSON 并返回给客户端
- WebSocket消息对象被包装为 { type, from, to, data, participantId } 形式发送
章节来源
- [httphandler.ts:398-558](file://src/class/httphandler.ts#L398-L558)
- [websockethandler.ts:192-200](file://src/class/websockethandler.ts#L192-L200)
- [signaling.js:117-138](file://client/src/signaling.js#L117-L138)
- [signaling.js:255-279](file://client/src/signaling.js#L255-L279)
### JSON 结构规范与字段含义
- Offer
- 字段connectionId, sdp, polite, type="offer", datetime
- 含义连接标识、SDP 描述、礼貌协商标志、消息类型、时间戳
- Answer
- 字段connectionId, sdp, type="answer", datetime
- 含义连接标识、SDP 描述、消息类型、时间戳
- Candidate
- 字段connectionId, candidate, sdpMLineIndex, sdpMid, type="candidate", datetime
- 含义连接标识、ICE 候选者、SDP 媒体行索引、SDP 媒体 ID、消息类型、时间戳
- 通用字段
- type消息类型connect/disconnect/offer/answer/candidate/on-message
- datetime消息创建时间戳毫秒
章节来源
- [服务端接口与WebSocket消息类型.md:141-234](file://src/服务端接口与WebSocket消息类型.md#L141-L234)
- [httphandler.ts:398-558](file://src/class/httphandler.ts#L398-L558)
### 实际消息交换示例与调试技巧
- HTTP 模式
- 客户端通过 PUT /signaling 创建会话,随后通过 PUT /signaling/connection 建立连接
- 使用 GET /signaling 获取所有消息,或分别 GET /signaling/offer、/answer、/candidate 拉取增量
- 使用 fromtime 参数实现增量拉取,避免重复处理
- WebSocket 模式
- 客户端发送 { type: "connect", connectionId } 建立连接
- 发送 { type: "offer"/"answer"/"candidate", from, data } 进行 SDP 交换
- 监听服务端推送的 offer/answer/candidate 消息并更新本地 PeerConnection
- 调试技巧
- 使用浏览器开发者工具查看网络面板中的 HTTP 请求与响应
- 在 WebSocket 面板观察消息收发,注意 participantId 与 from 字段
- 关注服务端日志输出,定位消息路由问题
- 使用测试用例参考消息格式与预期行为
章节来源
- [signaling.js:30-150](file://client/src/signaling.js#L30-L150)
- [websocket.ts:44-114](file://src/websocket.ts#L44-L114)
- [websockethandler.ts:192-200](file://src/class/websockethandler.ts#L192-L200)
- [signaling.test.js:89-208](file://client/test/signaling.test.js#L89-L208)
### 不同通信模式下的使用差异
- 公共模式Public
- 所有连接的客户端均可相互通信
- offer/answer/candidate 向所有其他客户端广播
- 适合点对点直连场景
- 私有模式Private
- 一个 connectionId 对应一个房间,包含 1 个 host 与多个 participants
- host 为第一个加入者polite=falseparticipants 为后续加入者polite=true
- host 可单播给特定 participant 或广播给所有 participantsparticipant 仅能发送给 host
- host 离开时房间关闭participants 被断开participant 离开房间仍保留
章节来源
- [服务端接口与WebSocket消息类型.md:489-505](file://src/服务端接口与WebSocket消息类型.md#L489-L505)
- [websockethandler.ts:150-167](file://src/class/websockethandler.ts#L150-L167)
- [httphandler.ts:280-289](file://src/class/httphandler.ts#L280-L289)
## 依赖关系分析
```mermaid
graph LR
O["Offer 类<br/>offer.ts"] --> HH["HTTP 处理器<br/>httphandler.ts"]
A["Answer 类<br/>answer.ts"] --> HH
C["Candidate 类<br/>candidate.ts"] --> HH
HH --> S["会话/连接映射(Maps)"]
HH --> WS["WebSocket 服务器<br/>websocket.ts"]
HH --> HWS["WebSocket 处理器<br/>websockethandler.ts"]
HWS --> O
HWS --> A
HWS --> C
```
图表来源
- [offer.ts:1-11](file://src/class/offer.ts#L1-L11)
- [answer.ts:1-8](file://src/class/answer.ts#L1-L8)
- [candidate.ts:1-12](file://src/class/candidate.ts#L1-L12)
- [httphandler.ts:63-77](file://src/class/httphandler.ts#L63-L77)
- [websockethandler.ts:5-8](file://src/class/websockethandler.ts#L5-L8)
- [websocket.ts:1-118](file://src/websocket.ts#L1-L118)
章节来源
- [offer.ts:1-11](file://src/class/offer.ts#L1-L11)
- [answer.ts:1-8](file://src/class/answer.ts#L1-L8)
- [candidate.ts:1-12](file://src/class/candidate.ts#L1-L12)
- [httphandler.ts:63-77](file://src/class/httphandler.ts#L63-L77)
- [websockethandler.ts:5-8](file://src/class/websockethandler.ts#L5-L8)
- [websocket.ts:1-118](file://src/websocket.ts#L1-L118)
## 性能考虑
- 增量拉取HTTP GET 支持 fromtime 参数,减少重复消息传输与解析开销
- 会话超时10 秒无请求自动清理会话,避免内存泄漏
- 广播策略:公共模式下广播所有消息,私有模式下按需单播/广播,降低网络负载
- 心跳检测可选的心跳机制ping/pong用于保持连接活跃避免被中间设备断开
[本节为通用建议,不直接分析具体文件]
## 故障排查指南
- HTTP 404检查会话 ID 是否正确传入请求头 Session-Id
- 消息未到达:确认通信模式(公共/私有)与连接配对是否正确
- polite 标志异常:检查连接顺序与私有模式下 host/participant 的角色分配
- Candidate 缺失:确认 ICE 候选者是否正确序列化sdpMLineIndex 与 sdpMid 是否匹配
- WebSocket 断开:检查心跳机制与网络稳定性,关注服务端日志
章节来源
- [httphandler.ts:128-145](file://src/class/httphandler.ts#L128-L145)
- [websockethandler.ts:404-430](file://src/class/websockethandler.ts#L404-L430)
- [websocket.ts:95-100](file://src/websocket.ts#L95-L100)
## 结论
Offer、Answer 与 Candidate 三类消息对象构成了 WebRTC 信令的核心载体。通过 HTTP 与 WebSocket 双通道,结合公共/私有两种通信模式,系统实现了灵活高效的信令交换能力。理解各字段的语义与消息流转过程,有助于在实际开发中快速定位问题并优化性能。
[本节为总结性内容,不直接分析具体文件]
## 附录
### API 一览HTTP
- GET /signaling/connection-ids
- PUT /signaling
- GET /signaling
- DELETE /signaling
- GET /signaling/connection
- PUT /signaling/connection
- DELETE /signaling/connection
- GET /signaling/offer
- POST /signaling/offer
- GET /signaling/answer
- POST /signaling/answer
- GET /signaling/candidate
- POST /signaling/candidate
章节来源
- [服务端接口与WebSocket消息类型.md:37-234](file://src/服务端接口与WebSocket消息类型.md#L37-L234)
### WebSocket 消息类型
- connect/disconnect连接生命周期
- offer/answer/candidateSDP 交换
- on-message通用消息
- broadcast广播消息
- call-request呼叫请求
- participant-joined/participant-left私有模式参与者变更
章节来源
- [服务端接口与WebSocket消息类型.md:262-486](file://src/服务端接口与WebSocket消息类型.md#L262-L486)