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

16 KiB
Raw Permalink Blame History

信令客户端

**本文引用的文件** - [client/src/signaling.js](file://client/src/signaling.js) - [client/test/signaling.test.js](file://client/test/signaling.test.js) - [client/test/mocksignaling.js](file://client/test/mocksignaling.js) - [client/src/logger.js](file://client/src/logger.js) - [src/signaling.ts](file://src/signaling.ts) - [src/class/httphandler.ts](file://src/class/httphandler.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/server.ts](file://src/server.ts) - [src/index.ts](file://src/index.ts) - [package.json](file://package.json)

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考量
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本文件系统性地阐述信令客户端模块的实现机制与协议设计,覆盖以下主题:

  • 与服务器的连接建立、消息收发与轮询拉取流程
  • 信令协议的消息格式、事件类型与状态同步机制
  • WebSocket 与 HTTP 轮询两种信令模式的实现差异与适用场景
  • 客户端状态管理(连接状态监控、重连与错误处理)
  • 实战示例(以“代码片段路径”形式给出,避免直接粘贴源码)

项目结构

前端信令客户端位于 client/src/signaling.js提供两类信令适配器

  • HTTP 轮询适配器:基于 fetch 的 GET/PUT/POST/DELETE 接口,周期性拉取消息
  • WebSocket 适配器:基于原生 WebSocket实时推送消息

后端信令服务位于 src/signaling.ts 与 src/class/httphandler.tsHTTP及 src/websocket.ts 与 src/class/websockethandler.tsWebSocket二者均通过统一的事件模型驱动前端。

graph TB
subgraph "前端"
FE_HTTP["HTTP 信令客户端<br/>client/src/signaling.js"]
FE_WS["WebSocket 信令客户端<br/>client/src/signaling.js"]
FE_LOGGER["日志工具<br/>client/src/logger.js"]
end
subgraph "后端"
BE_ROUTER["HTTP 路由<br/>src/signaling.ts"]
BE_HTTP_HANDLER["HTTP 处理器<br/>src/class/httphandler.ts"]
BE_WS_SERVER["WebSocket 服务器<br/>src/websocket.ts"]
BE_WS_HANDLER["WebSocket 处理器<br/>src/class/websockethandler.ts"]
end
FE_HTTP --> BE_ROUTER
FE_WS --> BE_WS_SERVER
BE_ROUTER --> BE_HTTP_HANDLER
BE_WS_SERVER --> BE_WS_HANDLER
FE_HTTP --- FE_LOGGER
FE_WS --- FE_LOGGER

图表来源

章节来源

核心组件

  • HTTP 信令客户端Signaling 类)
    • 负责会话创建/删除、连接建立/断开、offer/answer/candidate/on-message 的发送与轮询接收
    • 通过自定义事件分发消息connect/disconnect/offer/answer/candidate/on-message
  • WebSocket 信令客户端WebSocketSignaling 类)
    • 负责 WebSocket 连接生命周期、消息发送与事件分发
    • 支持 participant-joined/participant-left/broadcast 等扩展事件
  • 日志工具Logger
    • 提供启用/禁用与多种级别输出,便于调试

章节来源

架构总览

信令客户端与服务端通过两种模式协作:

  • HTTP 轮询:客户端周期性 GET /signaling 拉取消息;服务端按会话聚合 offer/answer/candidate/connect/disconnect 并按时间戳排序返回
  • WebSocket客户端直连 WebSocket服务端按连接组host/participants进行消息路由与广播
sequenceDiagram
participant C as "信令客户端"
participant S as "HTTP 服务端"
participant H as "HTTP 处理器"
C->>S : PUT /signaling (创建会话)
S->>H : createSession()
H-->>S : { sessionId }
S-->>C : { sessionId }
C->>S : PUT /signaling/connection (建立连接)
S->>H : createConnection()
H-->>S : { connectionId, polite }
S-->>C : { connect ... }
loop 轮询
C->>S : GET /signaling?fromtime=...
S->>H : getAll(fromtime)
H-->>S : { messages[], datetime }
S-->>C : { messages[], datetime }
C-->>C : 分发事件 (offer/answer/candidate/disconnect)
end
C->>S : DELETE /signaling (删除会话)
S->>H : deleteSession()
H-->>S : 200
S-->>C : 200

图表来源

章节来源

详细组件分析

HTTP 信令客户端Signaling 类)

  • 会话管理
    • start():若未获取 sessionId循环 PUT /signaling 创建会话,成功后进入轮询
    • stop()DELETE /signaling 清理会话并重置 sessionId
  • 连接管理
    • createConnection()/deleteConnection()PUT/DELETE /signaling/connection
  • 媒体协商
    • sendOffer()/sendAnswer()/sendCandidate()POST /signaling/offer|answer|candidate
  • 通用消息
    • sendMessage()POST /signaling/on-message
  • 消息拉取
    • loopGetAll()GET /signaling?fromtime=lastTime解析 messages 数组并分发事件
  • 事件分发
    • disconnect/offer/answer/candidate/on-message 等事件通过 CustomEvent 派发
classDiagram
class Signaling {
+running boolean
+interval number
+sessionId string
+headers() object
+url(method, parameter) string
+start() void
+stop() void
+createConnection(connectionId) Promise
+deleteConnection(connectionId) Promise
+sendOffer(connectionId, sdp) Promise
+sendAnswer(connectionId, sdp) Promise
+sendCandidate(connectionId, candidate, sdpMid, sdpMLineIndex) Promise
+sendMessage(connectionId, message) Promise
+getAll(fromTime) Promise
-loopGetAll() void
}

图表来源

章节来源

WebSocket 信令客户端WebSocketSignaling 类)

  • 连接建立
    • 构造函数根据协议选择 ws/wss监听 open/close/message
    • start():等待 isWsOpen 为真
    • stop():关闭连接并等待 isWsOpen 为假
  • 消息发送
    • createConnection()/deleteConnection()
    • sendOffer()/sendAnswer()/sendCandidate()
    • sendMessage():封装 type:"on-message" 数据
  • 消息接收与事件分发
    • onmessage解析 JSON按 type 分派 connect/disconnect/offer/answer/candidate/on-message/participant-joined/participant-left/broadcast
sequenceDiagram
participant C as "WebSocket 客户端"
participant WS as "WebSocket 服务端"
participant WH as "WebSocket 处理器"
C->>WS : CONNECT ws : //host
WS-->>C : onopen
C->>WS : {"type" : "connect","connectionId" : id}
WS->>WH : onConnect(ws, id)
WH-->>WS : 广播/通知
WS-->>C : {"type" : "connect", ...}
C->>WS : {"type" : "offer","from" : id,"data" : {"sdp",...}}
WS->>WH : onOffer(ws, data)
WH-->>WS : 路由/广播
WS-->>C : {"type" : "offer", ...}
C->>WS : {"type" : "on-message", "data" : {...}}
WS->>WH : onMessage(ws, data)
WH-->>WS : 转发
WS-->>C : {"type" : "on-message", ...}
C->>WS : CLOSE
WS-->>C : onclose

图表来源

章节来源

信令协议与消息格式

  • HTTP 模式
    • 会话PUT /signaling -> { sessionId }
    • 连接PUT /signaling/connection -> { connectionId, polite }
    • 消息GET /signaling?fromtime=... -> { messages[], datetime }
    • 消息类型connect/disconnect/offer/answer/candidate/on-message
    • offer/answer 字段connectionId, sdp, polite可选
    • candidate 字段connectionId, candidate, sdpMLineIndex, sdpMid
  • WebSocket 模式
    • 连接:{"type":"connect","connectionId":id}
    • 信令:{"type":"offer|answer|candidate","from":id,"data":{...},"participantId":...}
    • 普通消息:{"type":"on-message","data":{...}}
    • 扩展事件participant-joined/participant-left/broadcast
flowchart TD
A["HTTP 消息聚合"] --> B["按时间戳排序"]
B --> C["分发事件offer/answer/candidate/disconnect"]
D["WebSocket 消息路由"] --> E["按连接组(host/participants)转发"]
E --> F["广播/定向转发"]

图表来源

章节来源

状态管理与重连策略

  • HTTP 轮询
    • start() 中若 sessionId 为空则持续尝试创建会话,间隔由 interval 控制
    • loopGetAll() 中每次拉取后更新 lastTimeRequest避免重复消费
    • stop() 显式清理会话
  • WebSocket
    • 构造函数监听 open/closestart() 等待连接就绪
    • 建议在 onclose 中实现指数退避重连(可在上层封装)
  • 错误处理
    • on-message 解析失败时记录错误日志
    • HTTP 模式下 404/参数缺失等错误需上层捕获并提示

章节来源

代码示例(以路径引用代替代码)

章节来源

依赖关系分析

  • 前端依赖
    • client/src/signaling.js 依赖 client/src/logger.js
    • 测试依赖 client/test/signaling.test.js 与 client/test/mocksignaling.js
  • 后端依赖
    • src/server.ts 注册 /signaling 路由并挂载 HTTP 与 WebSocket 信令
    • src/signaling.ts 定义路由与鉴权中间件(会话校验)
    • HTTP 侧src/class/httphandler.ts 负责会话/连接/消息持久化与聚合
    • WebSocket 侧src/websocket.ts 与 src/class/websockethandler.ts 负责连接组与消息路由
graph LR
P["package.json"] --> FE["client/src/signaling.js"]
P --> BE_S["src/server.ts"]
BE_S --> BE_R["src/signaling.ts"]
BE_R --> BE_H["src/class/httphandler.ts"]
BE_S --> BE_W["src/websocket.ts"]
BE_W --> BE_WH["src/class/websockethandler.ts"]
FE --> LOG["client/src/logger.js"]

图表来源

章节来源

性能考量

  • HTTP 轮询
    • 通过 fromtime 参数避免重复拉取,提升效率
    • 合理设置 interval避免过于频繁导致带宽与 CPU 压力
  • WebSocket
    • 服务端支持心跳检测(注释中可见),可结合客户端 ping/pong 保持长连稳定
    • 连接组广播需控制消息规模,避免风暴
  • 会话超时
    • HTTP 处理器定期清理长时间无请求的会话,降低资源占用

章节来源

故障排查指南

章节来源

结论

本信令客户端模块提供了统一的事件接口,兼容 HTTP 轮询与 WebSocket 两种模式。HTTP 模式适合受限网络环境WebSocket 模式具备更低延迟与更丰富的连接组能力。通过清晰的事件分发与日志工具,开发者可以快速集成并调试信令流程。

附录