什么是WebRTC
WebRTC是一個由Google發(fā)起的實(shí)時通訊解決方案,其中包含視頻音頻采集,編解碼,數(shù)據(jù)傳輸,音視頻展示等功能,我們可以通過技術(shù)快速地構(gòu)建出一個音視頻通訊應(yīng)用。 雖然其名為WebRTC,但是實(shí)際上它不光支持Web之間的音視頻通訊,還支持Android以及IOS端,此外由于該項目是開源的,我們也可以通過編譯C++代碼,從而達(dá)到全平臺的互通。
WebRTC架構(gòu)

架構(gòu)組件
Your Web App
Web開發(fā)者開發(fā)的程序,Web開發(fā)者可以基于集成WebRTC的瀏覽器提供的web API開發(fā)基于視頻、音頻的實(shí)時通信應(yīng)用。
Web API
面向第三方開發(fā)者的WebRTC標(biāo)準(zhǔn)API(Javascript),使開發(fā)者能夠容易地開發(fā)出類似于網(wǎng)絡(luò)視頻聊天的web應(yīng)用,需要注意的是可能在不同瀏覽器中API接口名會不太一樣, 所以推薦使用這個JS適配器來協(xié)調(diào)各個瀏覽器的不同接口。 這些API可分成Media API、 RTCPeerConnection、Peer-to-peer Data API三類:
Media API
MediaStream:MediaStream用來表示一個媒體數(shù)據(jù)流。 MediaStreamTrack:在瀏覽器中表示一個媒體源。
RTCPeerConnection
RTCPeerConnection:一個RTCPeerConnection對象允許用戶在兩個瀏覽器之間直接通訊。 SDP: 用來描述當(dāng)前連接者想要傳輸?shù)膬?nèi)容,支持的協(xié)議類型,支持的編解碼類型等。 RTCIceCandidate:表示一個ICE協(xié)議的候選者,簡單的說,就是目標(biāo)節(jié)點(diǎn)的IP以及端口。 RTCIceServer:表示一個ICE Server,其主要用于當(dāng)前主機(jī)的IP發(fā)現(xiàn),通過和ICE Server通訊,我們會得到一組可供連接使用的IP:Port候選值,雙方通過交換ICE候選值來建立起連接。
Peer-to-peer Data API
DataChannel:數(shù)據(jù)通道( DataChannel)接口表示一個在兩個節(jié)點(diǎn)之間的雙向的數(shù)據(jù)通道,該通道可以設(shè)置成可靠傳輸或非可靠傳輸 。
WebRTC Native C++ API
本地C++ API層,使瀏覽器廠商容易實(shí)現(xiàn)WebRTC標(biāo)準(zhǔn)的Web API,抽象地對數(shù)字信號過程進(jìn)行處理。
Transport / Session
傳輸部分可基于TCP/UDP,會話層組件采用了libjingle庫的部分組件實(shí)現(xiàn)
AudioEngine
音頻引擎是包含一系列音頻多媒體處理的框架,包括從視頻采集卡到網(wǎng)絡(luò)傳輸端等整個解決方案。
VideoEngine
視頻引擎是包含一系列視頻處理的整體框架,從攝像頭采集視頻到視頻信息網(wǎng)絡(luò)傳輸再到視頻顯示整個完整過程的解決方案。
通訊內(nèi)容的確立
首先,兩個客戶端(Alice & Bob)想要創(chuàng)建連接,一般來說需要有一個雙方都能訪問的服務(wù)器來幫助他們交換連接所需要的信息。有了交換數(shù)據(jù)的中間人之后,他們首先要交換的數(shù)據(jù)是SessionDescription(SD),這里面描述了連接雙方想要建立怎樣的連接。

SD 從哪來
一般來說,在建立連接之前連接雙方需要先通過API來指定自己要傳輸什么數(shù)據(jù)(Audio,Video,DataChannel),以及自己希望接受什么數(shù)據(jù),然后Alice調(diào)用CreateOffer()方法,獲取offer類型的SessionDescription,通過公共服務(wù)器傳遞給Bob,同樣地Bob通過調(diào)用CreateAnswer(),獲取answer類型的SessionDescription,通過公共服務(wù)器傳遞給Alice。 在這個過程中無論是哪一方創(chuàng)建Offer(Answer)都無所謂,但是要保證連接雙方創(chuàng)建的SessionDescription類型是相互對應(yīng)的。Alice=Answer Bob=Offer | Alice=Offer Bob=Answer
SD 包含什么內(nèi)容
//版本
v=0
//<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>
o=- 3089712662142082488 2 IN IP4 127.0.0.1
//會話名
s=-
//會話的起始時間和結(jié)束時間,0代表沒有限制
t=0 0
//表示音頻傳輸和data channel傳輸共用一個傳輸通道傳輸?shù)拿襟w,通過id進(jìn)行區(qū)分不同的流
a=group:BUNDLE audio data
//WebRTC Media Stream
a=msid-semantic: WMS
//m=audio說明本會話包含音頻,9代表音頻使用端口9來傳輸,但是在webrtc中現(xiàn)在一般不使用,如果設(shè)置為0,代表不傳輸音頻
//使用UDP來傳輸RTP包,并使用TLS加密, SAVPF代表使用srtcp的反饋機(jī)制來控制通信過程
//111 103 104 9 0 8 106 105 13 110 112 113 126表示支持的編碼,和后面的a=rtpmap對應(yīng)
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126
//表示你要用來接收或者發(fā)送音頻使用的IP地址, webrtc使用ice傳輸,不使用這個地址, 關(guān)于ICE是什么后面會講到
c=IN IP4 0.0.0.0
//用來傳輸rtcp的地址和端口,webrtc中不使用
a=rtcp:9 IN IP4 0.0.0.0
//ice協(xié)商過程中的安全驗(yàn)證信息
a=ice-ufrag:ubhd
a=ice-pwd:l82NnsGm5i7pucQRchNdjA6B
//支持trickle,即sdp里面只描述媒體信息, ice候選項的信息另行通知
a=ice-options:trickle
//dtls協(xié)商過程中需要的認(rèn)證信息
a=fingerprint:sha-256 CA:83:D0:0F:3B:27:4C:8F:F4:DB:34:58:AC:A6:5D:36:01:07:9F:2B:1D:95:29:AD:0C:F8:08:68:34:D8:62:A7
a=setup:active
//前面BUNDLE行中用到的媒體標(biāo)識
a=mid:audio
//指出要在rtp頭部中加入音量信息
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
//當(dāng)前客戶端只接受數(shù)據(jù),不發(fā)送數(shù)據(jù),recvonly,sendonly,inactive,sendrecv
a=recvonly
//rtp,rtcp包使用同一個端口來傳輸
a=rtcp-mux
//下面都是對m=audio這一行的媒體編碼補(bǔ)充說明,指出了編碼采用的編號,采樣率,聲道等
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
//對opus編碼可選的補(bǔ)充說明,minptime代表最小打包時長是10ms,useinbandfec=1代表使用opus編碼內(nèi)置fec特性
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
//下面就是對Data Channel的描述,基本和上面的audio描述類似,使用DTLS加密,使用SCTP傳輸
m=application 9 DTLS/SCTP 5000
c=IN IP4 0.0.0.0
//可以是CT或AS,CT方式是設(shè)置整個會議的帶寬,AS是設(shè)置單個會話的帶寬。缺省帶寬是千比特每秒
b=AS:30
a=ice-ufrag:ubhd
a=ice-pwd:l82NnsGm5i7pucQRchNdjA6B
a=ice-options:trickle
a=fingerprint:sha-256 CA:83:D0:0F:3B:27:4C:8F:F4:DB:34:58:AC:A6:5D:36:01:07:9F:2B:1D:95:29:AD:0C:F8:08:68:34:D8:62:A7
a=setup:active
//前面BUNDLE行中用到的媒體標(biāo)識
a=mid:data
//使用端口5000,一個消息的大小是1024比特
a=sctpmap:5000 webrtc-datachannel 1024
以上就是一個SessionDescription的例子,雖然沒有video的描述,但是video和audio的描述是十分類似的。 SDP中有關(guān)于IP和端口的描述,但是WebRTC技術(shù)并沒有使用這些內(nèi)容,那么雙方是怎么建立"直接"連接的呢?建立起連接最關(guān)鍵的IP和端口是從哪里來的呢?這就需要ICE框架來完成這部分工作。
連接的建立
相關(guān)概念
ICE
互動式連接建立(Interactive Connectivity Establishment)提供的是一種框架,使各種NAT穿透技術(shù)(STUN,TURN...)可以實(shí)現(xiàn)統(tǒng)一。該技術(shù)可以讓客戶端成功地穿透遠(yuǎn)程用戶與網(wǎng)絡(luò)之間可能存在的各類防火墻。
NAT
網(wǎng)路位址轉(zhuǎn)換(Network Address Translation)可為你的裝置提供公用IP位址。路由器具備公用IP位址,而連上路由器的所有裝置則具備私有IP位址。接著針對請求,從裝置的私有IP對應(yīng)到路由器的公用IP與專屬的通訊端口。如此一來,各個裝置不需占用專屬的公用IP,亦可在網(wǎng)路上被清楚識別。
STUN
NAT 的UDP簡單穿越(Simple Traversal of UDP over NATs)是一種網(wǎng)絡(luò)協(xié)議,它允許位于NAT(或多重NAT)后的客戶端找出自己的公網(wǎng)地址,查出自己位于哪種類型的NAT之后以及NAT為某一個本地端口所綁定的Internet端端口。這些信息被用來在兩個同時處于NAT路由器之后的主機(jī)之間建立UDP通信。

即使透過 STUN 服務(wù)器取得了公用 IP 位址,也不一定能建立連線。因?yàn)椴煌腘AT類型處理傳入的UDP分組的方式是不同的。四種主要類型中有三種是可以使用STUN穿透:完全圓錐型NAT、受限圓錐型NAT和端口受限圓錐型NAT。但大型公司網(wǎng)絡(luò)中經(jīng)常采用的對稱型 NAT(又稱為雙向NAT)則不能使用,這類路由器會透過 NAT 布署所謂的「Symmetric NAT」限制。也就是說,路由器只會接受你之前連線過的節(jié)點(diǎn)所建立的連線。這類網(wǎng)絡(luò)就需要TURN技術(shù)。
TURN
中繼NAT實(shí)現(xiàn)的穿透(Traversal Using Relays around NAT)就是透過TURN服務(wù)器開啟連線并轉(zhuǎn)送所有數(shù)據(jù),進(jìn)而繞過Symmetric NAT的限制。你可透過TURN服務(wù)器建立連線,再告知所有端點(diǎn)傳送封包至該服務(wù)器,最后讓服務(wù)器轉(zhuǎn)送封包給你。這個方法更耗時且更占頻寬,因此在沒有其他替代方案時才會使用這個方法。

連接建立過程
介紹完ICE框架中各個獨(dú)立部分的含義之后,在讓我們來看一看整個框架是如何工作的。

1.連接雙方(Peer)通過第三方服務(wù)器來交換(Signalling)各自的SessionDescription數(shù)據(jù)。 2.連接雙方(Peer)通過STUN協(xié)議從STUN Server那里獲取到自己的NAT結(jié)構(gòu),子網(wǎng)IP和公網(wǎng)IP,端口,這里的IP和端口對我們稱之為ICE Candidate。 3.連接雙方(Peer)通過第三方服務(wù)器來交換(Signalling)各自ICE Candidates,如果連接雙方在同一個NAT下那他們僅通過內(nèi)網(wǎng)Candidate就能建立起連接,反之如果他們處于非對稱型NAT下,就需要STUN Server識別出的公網(wǎng)Candidate進(jìn)行通訊。 4.如果僅通過STUN Server發(fā)現(xiàn)的公網(wǎng)Candidate仍然無法建立連接,換句話說就是連接雙方(Peer)中至少有一方處于對稱NAT下,這就需要處于對稱NAT下的客戶端(Peer)去尋求TURN Server提供的轉(zhuǎn)發(fā)服務(wù),然后將轉(zhuǎn)發(fā)形式的Candidate共享(Signalling)給對方(Peer)。 5.連接雙方(Peer)向目標(biāo)IP端口發(fā)送報文,通過SessionDescription中涉及的密鑰以及期望傳輸?shù)膬?nèi)容,建立起加密長連接。