Webrtc本端和对端信令交互步骤

在官方库函数中,进入handle_signaling_message后开始解析msg消息结构体中的type,解析后会有三种type == "request",type == "answer",type == "candidate"

当对端发送 request

本端会先做四件事,这边会建立PeerConnection,创建本端DataChannel(createDataChannel(label))、添加视频轨(make_video_track(pc)),把其他的回调注册(onGatheringStateChange,onStateChange,nLocalCandidate)

后面执行c->setLocalDescription();


1. 本端 SDP

  • 库根据当前 PeerConnection 状态(已 addTrack 的视频轨、createDataChannel 的 SCTP 等)生成本地 SDP,并设为 local description。
  • 信令状态会从例如 stable → have-local-offer 一类变化(具体以 libdatachannel 为准)。

2. ICE 收集与 candidate

  • ICE gathering 会进入 InProgress,向 STUN 等发绑定请求、枚举 host / srflx 等候选。
  • 每拿到一个候选,会调注册的 onLocalCandidateemit_signaling_json,日志输出为``type=candidate 的 TX。
  • 收集结束状态改变 GatheringState::Complete,触发 onGatheringStateChange → 取 localDescription()emit_signaling_json 日志输出 type=offer + 整段 sdp

3. 连接状态

  • onStateChange 被调用,例如进入 ConnectingPC state=1 对应这里)
  • 等对端 answer 且本端 setRemoteDescription 成功后,才会继续到 Connectedstate=2)。

4. 建立连接时刻

  • setLocalDescription() 本身不会完成对端的 setRemoteDescription,也不会立刻刻 Connected;answer 要等信令从对端来。
  • DataChannel onOpen、video track->onOpen 一般在 SDP/ICE/DTLS 更往后才触发。

5. 代码的对应关系

setLocalDescription() ------> 告诉库「按当前视频轨 && DC 配置 开始出本端 SDP 并跑 ICE」;

之后由库回调 onLocalCandidate / onGatheringStateChangeemit_signaling_json,把 candidate 和 offer 发到信令通道。

/创建本端 DataChannel,代码写法分析

复制代码
 std::shared_ptr<rtc::DataChannel> local_dc;   //创建本端 DataChannel
        if (cfg.enable_datachannel) {
            const std::string label = cfg.data_channel_label.empty() ? std::string("app") : cfg.data_channel_label;
            local_dc = pc->createDataChannel(label);
            attach_dc_handlers(local_dc, "local");
        }
  1. pc->createDataChannel(label)

    调用 PeerConnection 的成员函数,返回类型是 std::shared_ptr<rtc::DataChannel>(库里声明好的)

  2. local_dc

    事先声明成 同一种类型 的变量:
    std::shared_ptr<rtc::DataChannel> local_dc;

    一开始是空指针(不指向任何 DataChannel)。

  3. local_dc = ...

    这是 shared_ptr 的赋值:把函数返回的那个 shared_ptr 拷给 local_dc, local_dc 和返回值指向同一条 DataChannel 对象,引用计数按 shared_ptr 规则增加。

createDataChannel 返回 shared_ptr<DataChannel>,你用赋值运算符把它保存到 local_dc 里,后面就用 local_dc 操作这条通道。


onGatheringStateChange指针写法分析:

复制代码
 pc->onGatheringStateChange([wpc = std::weak_ptr<rtc::PeerConnection>(pc), peer_id](rtc::PeerConnection::GatheringState st) {
            if (st != rtc::PeerConnection::GatheringState::Complete) {
                return;
            }
            auto locked = wpc.lock();
            if (!locked) {
                return;
            }
            auto desc = locked->localDescription();
            if (!desc) {
                return;
            }
            json out = {{"id", peer_id}, {"type", desc->typeString()}, {"sdp", std::string(*desc)}};
            emit_signaling_json(out);
            log_info("[webrtc_ldc] sent local SDP type={}", desc->typeString());
        });
  1. pc:当前这次 request 里新建的 PeerConnectionshared_ptr,指向真实对象。
  2. std::weak_ptr<rtc::PeerConnection>(pc):用 pc 拷贝构造一个 weak_ptr,让 wpcpc 指向同一块 PeerConnection,但 wpc 不计入引用计数。
  3. 必须传 pc:没有 shared_ptrweak_ptr 就不知道要弱引用谁;不能凭空 weak_ptr<T>() 就绑到正确对象上。

之后回调里 wpc.lock(),等价于:"当初注册时关心的那个 PeerConnection,现在还有没有活着的shared_ptr管着它?" 有就临时拿一个shared_ptr用一下,没有就说明已经关了。

相关推荐
wanhengidc1 小时前
云手机 游戏多开不卡顿
运维·服务器·网络·安全·web安全·游戏·智能手机
Yana.nice1 小时前
rpm -K检查RPM软件包完整性
linux·服务器·网络
Data_Journal1 小时前
Node.js网络爬取指南——简单易上手!
大数据·linux·服务器·前端·javascript
TEC_INO1 小时前
Linux58:rockx_vi_handle_thread线程的讲解
linux·运维·服务器
七夜zippoe1 小时前
OpenClaw Browser 自动化:表单填写实战
服务器·自动化·表单·browser·openclaw
袁煦丞 cpolar内网穿透实验室2 小时前
出差路上,服务器在我手机里
运维·服务器·docker·容器·智能手机·远程工作·cpolar
小此方2 小时前
Re:Linux系统篇(十三)特别篇: 实现Linux第⼀个系统程序−进度条
linux·运维·服务器
tedcloud1237 小时前
UI-TARS-desktop部署教程:构建AI桌面自动化系统
服务器·前端·人工智能·ui·自动化·github
AC赳赳老秦10 小时前
供应链专员提效:OpenClaw自动跟踪物流信息、更新库存数据,异常自动提醒
java·大数据·服务器·数据库·人工智能·自动化·openclaw