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用一下,没有就说明已经关了。

相关推荐
草莓熊Lotso19 小时前
【Linux网络】深入理解 HTTP 协议(三):静态资源服务、状态码与重定向实战
linux·运维·服务器·网络·c++·http
流浪00119 小时前
LInux系统篇(二):深入剖析 Linux 进程:状态变迁、优先级及调度切换逻辑
linux·运维·服务器
daad77719 小时前
记录一个串口模块没有回包的问题
linux·运维·服务器
晚风予卿云月19 小时前
【Linux】进程控制(一)—进程创建、进程终止与信号全流程详解
linux·运维·服务器·后端开发
七仔啊20 小时前
windows server服务器验机流程
运维·服务器·windows
Cx330❀20 小时前
【Linux网络】打破“一问一答”局限:从零构建全双工多线程UDP群聊系统
linux·运维·服务器·网络·网络协议·udp
码农小旋风20 小时前
Codex中文网 | Codex CLI 中文指南
运维·服务器·ide·人工智能·chatgpt·claude
通街市密人有20 小时前
解决实验室服务器无法连网问题
服务器
tedcloud12320 小时前
Dolt部署教程:打造可追踪数据变更的数据库环境
服务器·数据库·人工智能·学习·自动化·powerpoint
学且思20 小时前
SSE 是 HTTP/2 的服务器推送?
服务器·网络协议·http