課程地址:零聲學(xué)院 WebRTC入門與提高 https://ke.qq.com/course/435382?tuin=137bb271
技術(shù)支持QQ群:782508536
更多音視頻知識(shí)請(qǐng)點(diǎn)擊:專注音視頻開發(fā)
原文:[webrtc] 交互式連接建立(ICE)http://www.libsdl.cn/bbs/forum.php?mod=viewthread&tid=81
交互式連接建立是一種標(biāo)準(zhǔn)穿透協(xié)議,利用Stun和Turn服務(wù)器來幫助端點(diǎn)建立連接雪侥。市面上已有不少介紹ICE的資料先馆,像《WebRTC權(quán)威指南(第三版)》中的“9.2 交互式連接建立”畅形。但看了那些后摇展,有人還是不能理解,這里試著用一個(gè)實(shí)例來描述整個(gè)過程叁巨。ICE協(xié)議只是制定規(guī)范财岔,沒規(guī)定怎么實(shí)現(xiàn)細(xì)節(jié),在細(xì)節(jié)實(shí)現(xiàn)上這里參考Google的WebRTC龟虎。
上圖就是《WebRTC權(quán)威指南(第三版)》中的圖9.1璃谨。呼叫要交換兩種信息,一是候選地址鲤妥,二是媒體信息佳吞。候選地址用于建立網(wǎng)絡(luò)連接,它存儲(chǔ)著和網(wǎng)絡(luò)連接相關(guān)的參數(shù)棉安。媒體信息(SDP)用于描述要在對(duì)等連接上傳輸?shù)臄?shù)據(jù)底扳,包括音頻、視頻和數(shù)據(jù)贡耽。用路和車來比喻的話衷模,候選地址用于造路,媒體信息于用指定要跑什么車蒲赂。
在圖中阱冶,雙方是串行處理媒體、候選地址滥嘴,但實(shí)際中是并發(fā)的木蹬。舉個(gè)例子,主叫收到Answer后若皱,它仍可能在收集候選地址镊叁,然后通過信令服務(wù)器發(fā)向被叫。
除了主叫必須創(chuàng)建Offer才開始收集候選地址走触、被叫必須創(chuàng)建Answer才開始收集候選地址外晦譬,ICE代理是相互獨(dú)立地處理媒體和候選地址。(這結(jié)論細(xì)節(jié)參考底下的“四:選定候選地址饺汹,并啟動(dòng)媒體”)蛔添。
和“9.2 交互式連接建立”一樣, 這里也把ICE分為六個(gè)步驟。下圖是例子使用的網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)迎瞧。
<ignore_js_op style="word-wrap: break-word; color: rgb(68, 68, 68); font-family: Tahoma, Helvetica, SimSun, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">
</ignore_js_op>
一:收集候選地址
候選地址是或許可用于接收媒體以建立對(duì)等連接的<IP地址, 端口>對(duì)夸溶,它分四種類型。
| 類型 | 別名 | 如何傳給對(duì)端 | 用法 |
| 主機(jī)候選項(xiàng) | host | 信令服務(wù)器 | 從網(wǎng)卡中獲取的本地傳輸?shù)刂沸坠瑁绻说刂肺挥贜AT之后缝裁,則為內(nèi)網(wǎng)地址 |
| 服務(wù)器反射候選項(xiàng) | srflx | 信令服務(wù)器 | 從發(fā)送給Stun服務(wù)器的Binding檢查中獲取的傳輸?shù)刂贰H绻说刂肺挥贜AT之后足绅,則為最外層NAT的公網(wǎng)地址 |
| 對(duì)端反射候選項(xiàng) | prflx | Stun Binding請(qǐng)求 | 從對(duì)端發(fā)送的Stun Binding請(qǐng)求獲取的傳輸?shù)刂方莅蟆_@是一種在連接檢查期間新發(fā)生的候選項(xiàng) |
| 中繼候選項(xiàng) | relay | 信令服務(wù)器 | 媒體中繼服務(wù)器的傳輸?shù)刂贰Mㄟ^使用TURN Allocate請(qǐng)求獲取 |
具體到例子氢妈,以下是此階段將至少能收集到的候選地址粹污。為簡(jiǎn)單,不再寫A的IP2首量、B的IP2的服務(wù)器反射地址壮吩。
| 別名 | 類型 | 值 |
| ACand2 | srflx | 211.161.240.181(raddr: 192.168.1.105) |
| ACand1 | host | 192.168.0.204 |
| BCand3 | host | 192.168.0.181 |
二:交換候選地址
A通過信令服務(wù)器把ACand2加缘、ACand1拣宏、BCand3發(fā)向A。對(duì)端收到一個(gè)候選地址后會(huì)做什么勋乾?深入它之前讓引入兩種對(duì)象:P2PTransportChannel宋下、Connection。
ICE代理用P2PTransportChannel管理通道(Component)上的網(wǎng)絡(luò)傳輸市俊。什么是通道杨凑?Webrtc有個(gè)概念叫軌道(Track)滤奈,常見有視頻軌摆昧、音頻軌,而要發(fā)送一條軌道中數(shù)據(jù)蜒程,最多可能使用兩個(gè)通道绅你,分別是Rtp、Rtcp昭躺〖删猓肯定會(huì)有Rtp,Rtcp則可選领炫。一個(gè)P2PTransportChannel對(duì)應(yīng)一條通道偶垮,如果當(dāng)前會(huì)話要同時(shí)處理音頻、視頻,每條軌道又都包括Rtp似舵、Rtcp脚猾,那會(huì)話中就存在四個(gè)P2PTransportChannel對(duì)象。P2PTransportChannel用維護(hù)一張連接狀態(tài)表來管理網(wǎng)絡(luò)傳輸砚哗,表中一條記錄對(duì)應(yīng)一個(gè)Connection對(duì)象龙助。這里讓具體到A的視頻Rtp對(duì)應(yīng)的P2PTransportChannel,看它在收到BCand1后提鸟,P2PTransportChannel會(huì)向連接狀態(tài)表新增兩條記錄,即兩個(gè)Connection仅淑。這時(shí)已到通道称勋,地址須是ip:port對(duì)。
| 本地網(wǎng)卡地址(Port) | 對(duì)端地址 | 狀態(tài) |
| 192.168.1.105:60001 | 192.168.0.204:40001 | 未進(jìn)行過Stun檢查 |
| 172.16.40.6:60003 | 192.168.0.204:40001 | 未進(jìn)行過Stun檢查 |
此時(shí)A不知道該用哪個(gè)網(wǎng)卡IP才能把數(shù)據(jù)成功發(fā)向192.168.0.204涯竟,于是它只要在有可能的地址對(duì)就創(chuàng)建Connection铣缠。注意Connection只會(huì)基于網(wǎng)卡IP,即host昆禽,因?yàn)閷?duì)發(fā)送源來說蝗蛙,host才可能是源,其它的只是中間轉(zhuǎn)換出的地址醉鳖,像srflx捡硅。當(dāng)然,創(chuàng)建時(shí)會(huì)放棄明顯不可能的<網(wǎng)卡地址, 對(duì)端地址>對(duì)盗棵,舉個(gè)例子壮韭,網(wǎng)卡地址是ipv4,而對(duì)端地址是ipv6纹因。
當(dāng)收全BCand2、B$Cand3瞭恰,狀態(tài)表中就有6條記錄屯曹。
| 本地網(wǎng)卡地址 | 對(duì)端地址 | 狀態(tài) |
| 192.168.1.105:60001 | 192.168.0.204:40001 | 未進(jìn)行過Stun檢查 |
| 172.16.40.6:60003 | 192.168.0.204:40001 | 未進(jìn)行過Stun檢查 |
| 192.168.1.105:60001 | 11.92.14.8:50002 | 未進(jìn)行過Stun檢查 |
| 172.16.40.6:60003 | 11.92.14.8:50002 | 未進(jìn)行過Stun檢查 |
| 192.168.1.105:60001 | 192.168.0.181:40003 | 未進(jìn)行過Stun檢查 |
| 172.16.40.6:60003 | 192.168.0.181:40003 | 未進(jìn)行過Stun檢查 |
表中有一條、或多條惊畏、或沒有恶耽,能夠把A的視頻Rtp數(shù)據(jù)發(fā)向B的視頻Rtp通道,到底怎么個(gè)可能性就要執(zhí)行接下的Stun檢查颜启。
三:STUN檢查
在狀態(tài)表新建一條記錄偷俭,即一個(gè)Connection,很快就會(huì)在此Connection上進(jìn)行Stun檢查缰盏。Stun檢查具體操作是在此Connection上發(fā)Stun Binding請(qǐng)求涌萤。由于要能支持Stun應(yīng)答淹遵,每個(gè)ICE代理必須內(nèi)置Stun服務(wù)器功能。Stun檢查具體步驟見下圖负溪。
<ignore_js_op style="word-wrap: break-word; color: rgb(68, 68, 68); font-family: Tahoma, Helvetica, SimSun, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">
</ignore_js_op>
為什么說Stun檢查會(huì)發(fā)現(xiàn)prflx候選項(xiàng)合呐?假如A和Stun服務(wù)器之間連接狀態(tài)不好,在它收到B發(fā)來的srflx(11.92.14.8)之后還沒得出自個(gè)的srflx(211.161.240.181)笙以。雖然A沒得到自個(gè)的srflx淌实,但這不妨礙對(duì)B的srflx這個(gè)候選地址進(jìn)行Stun檢查,于是會(huì)向11.92.14.8發(fā)Stun請(qǐng)求猖腕。B收到這個(gè)請(qǐng)求拆祈,從請(qǐng)求解析出211.161.240.181。雖然這個(gè)地址在值上等于A的srflx倘感,但不是從信令服務(wù)器得到放坏,而是來自對(duì)端的Stun請(qǐng)求。此時(shí)B就會(huì)以這個(gè)prflx向狀態(tài)表新建Connection老玛。
A在之后終于向Stun服務(wù)器拿到了自個(gè)的srflx淤年,并通過信令服務(wù)器發(fā)向B。B發(fā)現(xiàn)這個(gè)srflx值對(duì)應(yīng)的Connection已存在蜡豹,就不會(huì)再創(chuàng)建了麸粮。
到此可得出個(gè)結(jié)論:兩種原因會(huì)導(dǎo)致新建Connection,一是從信令服務(wù)器收到候選地址镜廉,二是Stun檢查發(fā)現(xiàn)prflx弄诲。不同于從信令服務(wù)器得到地址而創(chuàng)建的Connection,Stun檢查時(shí)創(chuàng)建的Connection一開始就基本能確定連接是暢通的娇唯。
四:選定候選地址齐遵,并啟動(dòng)媒體
P2PTransportChannel會(huì)維護(hù)連接狀態(tài)表,并排序表中記錄(SortConnectionsAndUpdateState)塔插。排序指的是計(jì)算每條記錄的連接“成本”梗摇,把成本最低的排在第一條。如何計(jì)算成本想许?這涉及到很多因素伶授,比如發(fā)出Stun請(qǐng)求到收到應(yīng)答經(jīng)過了的時(shí)間,用時(shí)越少的“成本”自然會(huì)低些伸刃。
當(dāng)A有視頻Rtp數(shù)據(jù)要發(fā)送時(shí)谎砾,它檢查狀態(tài)表的第一條記錄,如果判斷出它的狀態(tài)是發(fā)送就緒捧颅,就會(huì)用此Connection進(jìn)行發(fā)送。否則直接放棄這個(gè)發(fā)送任務(wù)较雕。媒體模塊在處理數(shù)據(jù)的采集碉哑、編碼任務(wù)時(shí)挚币,不用考慮候選地址方面進(jìn)展怎樣了,只是要到發(fā)送時(shí)才關(guān)注下扣典,而即使不能發(fā)送也不會(huì)影響自個(gè)進(jìn)度妆毕;同樣,候選地址處理模塊也不會(huì)關(guān)注媒體處理模塊的進(jìn)度贮尖。這正是之前寫的一個(gè)結(jié)論:“除了主叫必須創(chuàng)建Offer才開始收集候選地址笛粘、被叫必須創(chuàng)建Answer才開始收集候選地址外,ICE代理是相互獨(dú)立地處理媒體和候選地址”湿硝。
維護(hù)表任務(wù)包括新建薪前、刪除記錄,以及修改記錄中的狀態(tài)字段关斜。刪除記錄示括、修改狀態(tài)都涉及到“長(zhǎng)連接”。
五:長(zhǎng)連接
為確保NAT映射和過濾規(guī)則不在媒體會(huì)話期間超時(shí)痢畜,ICE會(huì)不斷通過使用中的候選項(xiàng)對(duì)發(fā)送Stun連接檢查垛膝。具體到P2PTransportChannel,表現(xiàn)出來的是對(duì)狀態(tài)表中所有記錄隔段時(shí)間就要發(fā)送個(gè)Stun Binding請(qǐng)求丁稀。如果檢測(cè)到本來是暢通的Connection上Stun應(yīng)答超時(shí)了吼拥,那它就會(huì)更改該Connection狀態(tài),執(zhí)行表排序時(shí)就有可能會(huì)向下掉线衫,嚴(yán)重時(shí)會(huì)從狀態(tài)表刪除該記錄扔罪。
一記錄被刪除后,如果之后那候選地址的連接又恢復(fù)了桶雀,則會(huì)基于該候選地址重新創(chuàng)建Connection矿酵。
六:ICE重新啟動(dòng)
分析長(zhǎng)連接時(shí),我們已能得出個(gè)結(jié)論矗积,如果是網(wǎng)絡(luò)擁堵或通斷導(dǎo)致的狀態(tài)表變化全肮,P2PTransportChannel內(nèi)部就能處理。但是棘捣,如果基地址發(fā)生改變辜腺,像一網(wǎng)卡被禁用,這就超出P2PTransportChannel可處理范圍了乍恐,需重啟ICE评疗。