WebRTC閘道器伺服器單埠方案實現

starRTC發表於2018-09-05

標準WebRTC連線建立流程

這裡描述的是Trickle ICE過程,並且省略了通話發起與接受的信令部分。流程如下: 1) WebRTC A通過Signal Server轉發SDP OFFER到WebRTC B。WebRTC B做完本地處理以後,通過 Signal Server轉發SDP ANSWER到A。

2)A、B同時向STUN Server傳送Binding request請求自身的外網地址,並從STUN Server回包的MAPPED-ADDRESS中得到各自的外網地址;

3)A、B收集完內外網ICE Candidate,並通過Signal Server傳送給對方;

4)雙方開始做NAT穿越,互相給對方的ICE Candidate傳送STUN Binding Request;

5)NAT穿越成功,A、B之間的P2P連線建立,進入媒體互通階段。在這個過程中,我們看到了有三個核心的部分,SDP協商、ICE Candidate交換、Stun Binding Req/Res的連通性檢查。

WebRTC閘道器連線建立流程

在瞭解了標準WebRTC的建連流程以後,我們來看看WebRTC客戶端如何與閘道器建連。

首先,我們閘道器的Media Server擁有公網IP,因此Server就不需要通過Stun Server收集自身的公網IP。WebRTC客戶端先與閘道器Signal Server協商SDP,包括ICE Candidate,Media Server分配IP和埠作為閘道器的ice candidate傳送給客戶端。因為閘道器是公網IP,所以客戶端向這個IP傳送STUN Binding Request會被伺服器收到, 並回復Response。接著客戶端與閘道器媒體伺服器進行DTLS握手與祕鑰協商,在此基礎上進一步進行SRTP的音視訊通訊。至此,WebRTC客戶端與閘道器伺服器建連成功。

WebRTC閘道器伺服器媒體架構 最簡的伺服器端埠方案是我們可以為每個客戶端分配一個埠,伺服器上使用這個埠區分每個使用者,就像圖裡描述的A、B、C、D四個人在WebRTC閘道器伺服器上分別對應UDP埠10001~1004。這種方案邏輯上很簡單,很多開源的伺服器都採用這個方案,如janus。另外一個原因是使用了libnice庫在伺服器上來和客戶端做ice建連,類似的做法都是採用多埠的架構。 那麼多埠有什麼不足呢? 1)很多的網路出口防火牆對能夠通過的UDP埠是有限制的;

2)對於服務端來說開闢這麼多埠,安全性本身也有一定的問題,特別是運維同學,更是拒絕;

3)開闢這麼多的埠在Server端上,埠的開銷和效能均有一定的影響。那能否用單埠?使用單埠前,核心要解決的一個問題是:如何區分每一個RTP/RTCP包是屬於哪一個WebRTC客戶端。

為了解決這個問題,我們需要使用一些小技巧。首先,有幾個基礎知識點我們先了解一下。如下圖:

1)SDP offer和answer裡配置的ice-ufrag欄位裡面內容,原來是用來作為stun資料包的鑑權的,因此STUN Binding Request裡面的USERNAME欄位就是由上Offer和answer的ice-ufrag內容拼接而成。

2)傳送STUN Binding Request的客戶端本地udp fd,與ice建連成功後傳送媒體資料的udp fd是同一個,也就是說Server上看到的ip port是同一個。

有了上面的背景知識,你肯定已經大致有一個方案了。我們來看看實現細節是怎麼樣的:

1)在伺服器給Web端的SDP Answer中設定ice-ufrag為roomid/userid,其中RoomID和UserID是通話業務層分配的內容,用於區分每對通話以及參與者。接著做Ice candidate協商,Web端開始做連通性檢測,也就是stun binding request裡的USERNAME為SDP local和remote的ice-ufrag指定內容。

2)伺服器收到stun binding request的客戶端ip和埠,並正常回stun binding response。

3)記錄客戶端地址與使用者的資訊的對映關係。

4)伺服器收到一個rtp/rtcp媒體資料包,通過包的源ip和埠,查詢對映表就可以識別這個包屬於哪個使用者。

WebRTC客戶端使用PeerConnection來表示不同的媒體連線,接下來我們將介紹如何選擇PeerConnection的方案。

線上體驗單埠直播與一對一視訊通話:github.com/starrtc/and…

相關文章