1.什么时候发
- 在
request分支末尾调pc->setLocalDescription()。 - 库开始 ICE gathering,在收集过程中每当产生一条新的本地 candidate,就回调
onLocalCandidate一次。 - lambda 里立刻组 JSON 并
emit_signaling_json,所以信令上会出现多条type=candidate;
时间顺序上:一般在 setLocalDescription 之后很快就会出现(先 PC state=1,srflx 那条 candidate);第一条 host 往往更早或几乎同时,取决于库枚举网卡的顺序。
第一条candidate和第二条candidate内容
第一次typ host ------ 本机网卡上的地址(如 192.168.6.221)。
第二次:typ srflx ------ 经 STUN 看到的 NAT 反射公网地址。
<?xml version="1.0" encoding="UTF-8"?>
<signaling>
<id>MBF672lwa7</id>
<type>candidate</type>
<candidate><![CDATA[candidate:1 1 UDP 2114977791 192.168.6.161 46924 typ host]]></candidate>
<mid>cam-video</mid>
</signaling>
[17:14:54.779] [webrtc_ldc] PC state=1 peer=MBF672lwa7
2026-05-14 17:14:54.840 WARN [4544] [rtc::impl::IceTransport::LogCallback@390] juice: Send failed, errno=101
[17:14:55.030] [webrtc_ldc] signaling TX
<?xml version="1.0" encoding="UTF-8"?>
<signaling>
<id>MBF672lwa7</id>
<type>candidate</type>
<candidate><![CDATA[candidate:2 1 UDP 1678769919 183.238.154.133 6313 typ srflx raddr 0.0.0.0 rport 0]]></candidate>
<mid>cam-video</mid>
</signaling>
2.Candidate带什么信息
每条 candidate 消息里的有效载荷就是 JSON 里的字段,例如:
candidate:一整条 ICE candidate 字符串(协议、优先级、IP、端口、typ host/typ srflx等)。mid:这条候选对应 SDP 里哪条 m-line(你是cam-video,即视频)。id:会话里的peer_id,对端用来知道是同一拨信令。
第一次:typ host ------ 本机网卡上的地址(如 192.168.x.x)。
第二次:typ srflx ------ 经 STUN 看到的 NAT 反射公网地址。
SDP 里后面 a=candidate:... 还会再带一遍(offer 里在 a=end-of-candidates 前也有这两行),属于 SDP 内嵌候选;单独发的那两次 JSON 是 Trickle ICE,让对端不必等整份 SDP就能先加候选。