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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章