WebRTC建立会话流程分析

WebRTC建立会话流程总结


了解如何运行PeerConnection Demo后,熟悉运行流程可以做为深入学习WebRTC的切入点。本节重点解释客户端双方建立会话时交互的主要信令(控制会话的文本协议)和与信令相关的 WebRTC API。


准备工作


peerconnection_client 工程主要分为三个部分,main_wnd.h 是视图类,主要包括用户界面相关代码;conductor.h是控制器,负责响应界面行为,控制会话的生命周期等;peer_connection_client.h是传输层,用于传输相应的信令。

 


为了方便理解客户端通信的建立步骤,可以稍加改动peerconnection_client的源代码使其从2个客户端的通信变为1个客户端的回环测试(loopback)。打开 src/all.sln, 修改 Conductor::StartLogin()函数为:

void Conductor::StartLogin(const std::string& server, int port) {
  InitializePeerConnection();
  ReinitializePeerConnectionForLoopback();
  return;

  if (client_->is_connected())
    return;
  server_ = server;
  client_->Connect(server, port, GetPeerName());
}

修改后只需要使用1个客户端就可以进行音视频回环测试,点击"Connect"按钮就可以看到自己的摄像头。这样便于熟悉本例的流程架构。


流程分析

流程总结


WebRTC建立通信的基本流程如下图所示,其中:

 


* 步骤1-2中主叫(Caller) 先配置会话的基本参数,比如本次会话是否包含音频流或者视频流等参数;再根据会话的参数创建Offer SDP(Session Description Protocol)后通过信令服务器转发给被叫(Callee)。

* 步骤3,5,6中被叫保存主叫的Offer SDP, 并依据Offer SDP创建Answer SDP,发送给主叫。

* 步骤8中主叫保存了被叫的Answer SDP,至此主叫和被叫双方都保存了己方和对方的SDP

* 步骤9,10中主叫发送自己的IceCandidate给被叫方。

* 步骤11,12中被叫发送自己的IceCandidate给主叫。

* 主叫和被叫双方都接收到对方的IceCandidate后,就可以建立连接了。


生成SDP


SDP是 SessionDescription Protocol的简称,它是一套描述流媒体交互参数的标准协议,即RFC4566。WebRTC使用SDP协议描述会话参数。

主叫(Caller)生成SDP的流程如下图所示:

 

* 调用PeerConnectionInterface::CreateOffer()生成的 Offer SDP会异步通知给Conductor::OnSuccess()。

* 被叫生成的Answer SDP 会从Conductor::OnMessageFromPeer传过来,然后通过PeerConnectionInterface::SetRemoteDescription接口设置。

* 被叫调用 PeerConnectionInterface的对应接口以及顺序和主叫有一定区别,具体为:SetRemoteDescription() -> CreateAnswer() -> SetLocalDescription()。

* 对于主叫,SetLocalDescription()的参数为Offer SDP,SetRemoteDescription()的参数为Answer SDP。

* 对于被叫,SetRemoteDescription()的参数为为Offer SDP, SetLocalDescription()的参数为Answer SDP。

* WebRTC通过如下常量来区分Offer SDP和Answer SDP。

const char SessionDescriptionInterface::kOffer[] = "offer";
const char SessionDescriptionInterface::kPrAnswer[] = "pranswer";
const char SessionDescriptionInterface::kAnswer[] = "answer";

* 如果是回环测试(loopback),PeerConnectionInterface的相关接口调用以及顺序没有区别,只是不需要通过PeerConnectionClient由服务器转发消息。

只有当PeerConnectionInterface的 SetLocalDescription() 以及SetRemoteDescription()接口被正确调用后,才可以设置 IceCandidate。


处理IceCandidate


ICE的全称是Interactive Connectivity Establishment。也是由IETF定义的一套标准协议,即RFC5245。它提供了一套标准的框架方法用于解决两点间的通信,并且优先选择点对点的通信方式;如果无法建立点对点通信也可以通过服务器转发。ICE框架的基本原理很简单,即对每一种可能的连接方式定义优先级,并逐个尝试,尝试连接成功且优先级最高的方式就是最后被选择的通信方式。

ICE使用STUN(Session Traversal Utilities for NAT)协议用于网络地址转换(NAT, Network Address Translation);使用TURN(Traversal Using Relay NAT)协议用于消息转发。

可以把一个IceCandidate当作成一个(IP地址+端口号+优先级)的组合。WebRTC会尝试ping每一个对方发送过来的IceCandidate。从中选择可以ping通的优先级最大的IceCandidate用于交换媒体数据。

在调用PeerConnectionInterface::SetLocalDescription() 和 PeerConnectionInterface::SetRemoteDescription()成功后,WebRTC就开始自动收集本地的IceCandidate。收到到的IceCandidate会异步通知到Conductor::OnIceCandidate()函数,然后直接发送给对方。对方接收到IceCandidate后调用PeerConnectionInterface::AddIceCandidate()接口尝试连接它。

当ICE的连接状态发生改变时会调用Conductor::OnIceConnectionChange(),此例并没有处理状态变化所以在conductor.h头文件里面实现了空方法。ICE的连接状态有如下几种:

  enum IceConnectionState {
    kIceConnectionNew, // 初始状态
    kIceConnectionChecking, // 连接中
    kIceConnectionConnected, // 连接成功
    kIceConnectionCompleted, // 连接成功
    kIceConnectionFailed, // 连接失败
    kIceConnectionDisconnected, // 连接断开,有可能继续尝试连接
    kIceConnectionClosed, // 连接关闭,最终状态
    kIceConnectionMax,
  };

WebRTC将媒体数据抽象为webrtc::MediaStreamInterface对象,可以通过Conductor::OnAddStream()回掉函数获得Stream中包含的VideoTrack来渲染视频数据。


小结


* 无论是主叫或被叫,想要通信成功都需要获得的重要参数: Local SDP;Remote SDP;Remote IceCandidate;

* 与上述对应的PeerConnectionInterface的接口:SetLocalDescrpition(), SetRemoteDescription(), AddIceCandidate()。

* 主叫和被叫调用上述接口的顺序有一些差别。

* 获取Local SDP 与Local IceCandidate的回掉接口分别为: Conductor::OnSuccess();Conductor::OnIceCandidate()。

* 通过Conductor::OnSuccess()获取SDP后,可以修改默认参数,如视频编码器默认从VP8改为H.264。

Conductor::OnIceConnectionChange()通知的状态与信令服务器的连接状态(PeerConnectionServer)无关。

* 如果注释掉如下代码,会话就不会包含音频流:

  //stream->AddTrack(audio_track);
  stream->AddTrack(video_track);

* 可以使用Visual Studio 工具调试确认SDP和IceCandidate的格式。


参考文献


https://en.wikipedia.org/wiki/Session_Description_Protocol

https://en.wikipedia.org/wiki/Interactive_Connectivity_Establishment

http://blog.csdn.net/chenyefei/article/details/52100438

猜你喜欢

转载自blog.csdn.net/chenxiemin/article/details/79331137