SDL中文论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz

交互式连接建立(ICE)

查看数: 16483 | 评论数: 3 | 收藏 0
关灯 | 提示:支持键盘翻页<-左 右->
    组图打开中,请稍候......
发布时间: 2016-10-21 14:16

正文摘要:

本帖最后由 ancientcc 于 2017-2-4 22:56 编辑   交互式连接建立是一种标准穿透协议,利用Stun和Turn服务器来帮助端点建立连接。市面上已有不少介绍ICE的资料,像《WebRTC权威指南(第三版)》中的“9.2 交互式连 ...

回复

ancientcc 发表于 2018-2-13 09:33:59

传输数据

  1. MediaConstraintsInterface--->RTCOfferAnswerOptions-->cricket::MediaSessionOptions(开始出现数组)-->cricket::SessionDescription-->JsepSessionDescription
复制代码
JsepSessionDescription是实现SessionDescriptionInterface接口的类。接口中有description()方法返回之前传给它的SessionDescription对象(desc)。SetLocalDescription会以desc为参数调用CreateChannels,后者创建声音、视频、数据轨道。
  1. RTCError PeerConnection::CreateChannels(const SessionDescription& desc);
复制代码

A:如何由RTCOfferAnswerOptions生成cricket::MediaSessionOptions?
  1. void PeerConnection::GetOptionsForPlanBOffer(const PeerConnectionInterface::RTCOfferAnswerOptions& offer_answer_options, cricket::MediaSessionOptions* session_options);
复制代码
在PeerConnection有一个std::vector<rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>> transceivers_变量,单元是RtpTransceiver,字段media_type_指示了要传输的数据类型,当前也就是三种,MEDIA_TYPE_AUDIO
、MEDIA_TYPE_VIDEO、MEDIA_TYPE_DATA。transceivers_决定了是否要在MediaSessionOptions存在声音、视频。但数据靠的不是这种方法,而是HasDataChannels()。
  1. bool PeerConnection::HasDataChannels() const {
  2.         return !rtp_data_channels_.empty() || !sctp_data_channels_.empty();
  3. }
复制代码
PeerConnection::Initialize会强制创建含两个RtpTransceiver的transceivers_,一个是audio、一个是video。(这是否意味着一次session必须同时传audio、video?)

我现在还没有找到让HasDataChannels()返回true的办法。

传输数据或是rtp(enable_rtp_data_channel=true)或是sctp。
ancientcc 发表于 2017-1-10 11:09:52

app编程

本帖最后由 ancientcc 于 2017-1-10 11:18 编辑

配置stun/turn服务器
在控制ICE模块上,app要做的是设置RTCConfiguration,然后把它作为参数传给PeerConnectionFactory::CreatePeerConnection。对RTCConfiguration,其它可用默认值,除了配置stun/turn服务器,即当中的servers字段。servers字段的类型是IceServer。
  1. struct IceServer {
  2.         std::string uri;
  3.         std::vector<std::string> urls;
  4.         std::string username;
  5.         std::string password;
  6.         ......
  7. };
复制代码

IceServer中有两个和服务器域名有关的url:uri、urls。当urls不空时,只解析urls,忽略uri。当urls空时,才解析uri。当urls、uri都是空时,参数错误。看webrtc写的,它是建议用urls,废弃uri。

urls是std::vector,也就是说一次会话可同时指定多个stun服务器,或多个turn服务器。接下说说字符串格式。[]表示可选,<>表示变量。
  1. stun服务器格式:stun[s]:<域名>:<端口号>。以下是两个例子。
  2. stun:133.130.113.73:3478
  3. stuns:133.130.113.73
复制代码

  • 默认端口号3478。
  • stuns是以安全为目的stun,即stun+ssl。

  1. turn服务器格式:turn[s]:[用户名@]<域名>:<端口号>[?transport=<传输类型>]。以下是两个例子。
  2. turns:turn.l.google.com:4378
  3. turn:test@turn.l.google.com:4378?transport=udp
复制代码

  • 默认端口号3478。
  • transport值可以是“upd”或“tcp”,默认“udp”。
  • turns是以安全为目的turn,即turn+ssl。当是turns,内部会强制使用5349端口,transport=tls。
  • 字符串中可指定用户名。当字符串中有用户名时,它会覆盖掉IceServer中的username字段。
  • 字符串不能指定密码,密码只能设在IceServer的password字段。

注:<webrtc>/api/peerconnection.cc的ParseIceServers负责解析IceServer。

查看收集/连接状态
到现在,我不知道app层如何判断正使用的连接是中继还是穿透。
  1. class PeerConnectionObserver {
  2.         ......
  3.         virtual void OnIceConnectionChange(PeerConnectionInterface::IceConnectionState new_state) = 0;
  4.         virtual void OnIceGatheringChange(PeerConnectionInterface::IceGatheringState new_state) = 0;
  5. };
复制代码

app可通过重载这两函数查看收集/连接状态。注:以下提到的Channel指P2PTransportChannel。

IceGatheringState指示收集对端候选地址到了什么状态,它有三个值。
状态描述
kIceGatheringNew初始值
kIceGatheringGatheringPeerConnection::SetLocalDescription退出前改到此状态,表示正在收集
kIceGatheringComplete表示所有的Channel都有了有效的对端候选地址。不等于通过了stun检查,当是relay时,只是收到了中继地址而已

不论IceGatheringState,还是IceConnectionState, 改变状态主要发生在TransportController::UpdateAggregateStates_n()。

对gathering_state,它查询P2PTransportChannel::gathering_state_变量,如果有一条Channel的gathering_state_不是kIceGatheringNew(或kIceGatheringGathering,或kIceGatheringComplete),那就是kIceGatheringGathering,如果都是kIceGatheringComplete,则就是kIceGatheringComplete。

Channel是什么时候从kIceGatheringNew到kIceGatheringGathering?PeerConnection::SetLocalDescription退出前。kIceGatheringGathering何时到kIceGatheringComplete?非relay类型,通过了Stun检查;relay时,收到一个中继地址。

IceGatheringState对调试有用,但对使用app的人来说,可能没啥用。它们可能应该关心IceConnectionState。
状态描述
kIceConnectionNew初始值
kIceConnectionChecking对主叫,收到Answer后会进入此状态。对被叫,使用了对端的第一个候选地址后进入此状态。它们共同点是收到了对端发来的数据,证明对端是存在的。
kIceConnectionConnected至少一条Channel有了可用的Connection。连接状态表第一条发送就绪。
kIceConnectionCompleted所有Channel有可用的Connection。
kIceConnectionFailed
kIceConnectionDisconnected
kIceConnectionClosed关闭了会话。
kIceConnectionMax

注:webrtc原码存在两处IceConnectionState定义,<webrtc>/api/peerconnectioninterface.h和<webrtc>/p2p/base/jseptransport.h。它们定义的值不一样,将来应该会统一。

由于webrtc默认开启绑定,这使得整会话就存在一条Channel。一旦该Channel有了可用的Connection,则是所有Channel都有了,这就让kIceConnectionConnected基于等同kIceConnectionCompleted。
状态提示
kIceConnectionNew正等待对方接听
kIceConnectionChecking正尝试和对方建立连接
kIceConnectionConnected建立了连接,启动聊天
kIceConnectionCompleted聊天中

Archiver|手机版|小黑屋|丽谷软件|libsdl.cn

GMT+8, 2025-5-1 16:51 , Processed in 0.100508 second(s), 24 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表