webrtc的P2P穿透部分是由libjingle實現的.
步驟順序大概是這樣的:
1. 嘗試直連.
2. 通過stun服務器進行穿透
3. 無法穿透則通過turn服務器中轉.
stun 服務器比較簡單. 網上也有很多公開的stun服務器可以用於測試. 例如 stun.ideasip.com
這里需要注意一下. 我在做Android應用時. 在少數老舊的手機上出現過一個bug:
PeerConnection close時非常慢. 大概需要50~80s.
后來反復檢查, 才發現問題出在公用的stun服務器響應比較慢.
解決辦法就是在自己搭一個stun服務器即可.
具體原因應該是: 一直在進行ice探測(stun bind request). 關閉的時候worker 線程因為網絡卡住了, 然后main線程等待. 這個不太好查. 可能需要打很多log來定位代碼.
無法穿透的時候就需要 turn 服務器來保證視頻通話的成功率.
turn 包含了stun的功能. 所以只需要部署turn服務器即可.
服務器代碼可以從這里獲取: https://code.google.com/p/coturn/
coturn 在原來的turnserver上增加了一些高級特性. (這是作者的描述, 兩個項目是同一個作者. 作者更推薦使用coturn).
coturn 支持tcp, udp, tls, dtls 連接.
coturn 支持Linux bsd solaris mac os. 暫不支持windows (未來會支持)
下面說一下安裝和配置.
1. coturn 的底層網絡部分依賴libevent. 所以需要先安裝libevent2, 地址在此 http://libevent.org/
2. coturn的安裝很簡單. configure make make install 三部曲就完事了.
3. coturn的文檔說明挺詳細的. 但比較多. 我只是大概說明下.
更具體的說明可以看 源碼目錄下的README.turnserver README.turnadmin README.turnutils
在bin目錄下生成六個可執行文件
turnadmin turnutils_peer turnutils_stunclient
turnserver turnutils_rfc5769check turnutils_uclient
turnserver 就是我們需要的服務器.
turnadmin 用來管理賬戶.
turnutils_stunclient 用於測試stun服務
turnutils_uclient 用於測試turn服務. 模擬多個UDP,TCP,TLS or DTLS 類型的客戶端
example 目錄主要是示范如何配置和使用turn. 包含一些測試用例.
example/etc 下是pem證書和conf配置文件
example/var/db 下是sqlite的db庫. 用於示范數據庫的格式.
coturn 支持三種配置. 命令行, conf文件和數據庫. 數據庫支持sqlite, MySQL, postgresql, MongoDB, Redis.
examples\scripts 下一些測試用例:
loadbalance 示范如何進行負載均衡. 設置一個master turn server 然后配置若干個slave turn server.
longtermsecure 示范如何使用long-term 驗證
longtermsecuredb 與 longtermsecure 類似, 不過是從數據庫配置
shorttermsecure 示范如何使用short-term驗證.
restapi 示范了web方面的使用.
stun 定義了兩種驗證方式.
Long-Term Credential
Short-Term Credential
具體可以參考stun標准 http://tools.ietf.org/html/rfc5389#section-15.4
但是對於webrtc而言. 僅支持long-term .
http://www.ietf.org/proceedings/87/slides/slides-87-behave-10.pdf
TURN REST Server API
這個PDF 描述了. turn服務器和客戶端的交互流程.
4. 簡單的使用
turnserver -o -a -f -v --mobility -m 10 --max-bps=100000 --min-port=32355 --max-port=65535 --user=ling:ling1234 --user=ling2:ling1234 -r demo
-m 10 表示啟動十個relay線程.
--max-bps=100000 限制最大速度為100KB/s.
添加了兩個用戶ling 和ling2.
可以直接使用turnutils_uclient -u ling -w ling1234 來測試. turnutils_uclient 有很多參數可以配置的.
- webrtc::PeerConnectionInterface::IceServer turnServer;
- turnServer.uri = "turn:ip";
- turnServer.username = "ling";
- turnServer.password = "ling1234";
- servers.push_back(turnServer);
c++ webrtc中可以這樣配置turn. web/android/iOS 也是類似的.
如果從安全性方面考慮. 可以為賬戶生成key, 這樣就可以直接通過key登錄. 而不需要提供密碼.
key 通過turnadmin生成, 需要(username, password, realm) . realm是啟動turn server時-r 參數指定的.
- turnadmin -k -u ling -p ling1234 -r demo
- 0xccba8f3a6a025a38eb4a0e795fc92705