翻譯?http://www.html5rocks.com/en/tutorials/webrtc/infrastructure/
筋遭!WebRTC中文社區(qū)原創(chuàng)慢睡,轉(zhuǎn)載請(qǐng)注明出處痴施,謝謝,水平有限宇驾,部分意思可能不到位寺谤,建議參考英文原帖希俩!
WebRTC 可以p2p視頻通話(huà)
但是...
WebRTC 仍然需要幾個(gè)服務(wù):
信令服務(wù): 使客戶(hù)端之間交換數(shù)據(jù)用來(lái)協(xié)調(diào)建立通話(huà)
NAT穿透服務(wù):應(yīng)付NATs和防火墻
這篇文章會(huì)教你怎么搭建信令服務(wù)档押,和用STUN/TURN服務(wù)去做nat穿透逞力。另外煌往,我們會(huì)解釋W(xué)ebRTC是怎么做到多端通話(huà)的倾哺。以及如何和VoIP/PSTN(電話(huà))建立通話(huà)。
如果你對(duì)WebRTC還沒(méi)有基礎(chǔ)刽脖,我們強(qiáng)烈建議你先看下Getting Started With WebRTC羞海。
一.什么是信令服務(wù)(Signaling)?信令是一個(gè)協(xié)調(diào)溝通的過(guò)程曲管,為了讓一個(gè)WebRTC應(yīng)用發(fā)起一個(gè)“通話(huà)”却邓,客戶(hù)端間需要交換以下信令信息:1.發(fā)起和關(guān)閉一個(gè)通話(huà)的控制信息;2.錯(cuò)誤信息院水;3.媒體元數(shù)據(jù)腊徙,比如編碼解碼設(shè)置,帶寬和媒體類(lèi)型檬某;4.Key數(shù)據(jù)撬腾,用于確保安全通訊;5.網(wǎng)絡(luò)數(shù)據(jù)恢恼,比如主機(jī)在外網(wǎng)下的IP地址和端口民傻。客戶(hù)端的信令處理需要一種來(lái)回傳遞信息的方法,這種機(jī)制沒(méi)有被WebRTC定義漓踢,你需要自己去創(chuàng)建它牵署。下面我們將描繪幾種構(gòu)建信令服務(wù)的方法。在此之前喧半,先講幾個(gè)概念……為什么WebRTC沒(méi)有定義信令碟刺?為了避免冗余和最大化兼容已經(jīng)確立的技術(shù),WebRTC沒(méi)有指定信令的方法和協(xié)議薯酝。-------------------------------(WebRTC設(shè)計(jì)思想是完全指定和控制媒體層半沽,但是讓signaling層盡量脫離應(yīng)用,原因是不同的應(yīng)用可能會(huì)使用不同的協(xié)議吴菠,比如已經(jīng)存在的SIP或者Jingle呼叫協(xié)議等者填。這份協(xié)議中,需要交換的關(guān)鍵信息是多媒體會(huì)議的描述信息做葵,包括在媒體層確定必要的傳輸方式和 媒體配置信息)------------------------------------------------JSEP的結(jié)構(gòu)同樣避免了讓瀏覽器保存狀態(tài)信息占哟,如果讓瀏覽器成為一個(gè)保存信令狀態(tài)的機(jī)器,會(huì)出現(xiàn)一個(gè)問(wèn)題酿矢,就是每次當(dāng)頁(yè)面重載的時(shí)候榨乎,信令會(huì)丟失。所以更好的方案是用服務(wù)器保存信令狀態(tài)瘫筐。
var signalingChannel = new SignalingChannel();
var configuration = {
'iceServers': [{
'url': 'stun:stun.example.org'
}]
};
var pc;
// call start() to initiate
function start() {
pc = new RTCPeerConnection(configuration);
// send any ice candidates to the other peer
pc.onicecandidate = function (evt) {
if (evt.candidate)
signalingChannel.send(JSON.stringify({
'candidate': evt.candidate
}));
};
// let the 'negotiationneeded' event trigger offer generation
pc.onnegotiationneeded = function () {
pc.createOffer(localDescCreated, logError);
}
// once remote stream arrives, show it in the remote video element
pc.onaddstream = function (evt) {
remoteView.src = URL.createObjectURL(evt.stream);
};
// get a local stream, show it in a self-view and add it to be sent
navigator.getUserMedia({
'audio': true,
'video': true
}, function (stream) {
selfView.src = URL.createObjectURL(stream);
pc.addStream(stream);
}, logError);
}
function localDescCreated(desc) {
pc.setLocalDescription(desc, function () {
signalingChannel.send(JSON.stringify({
'sdp': pc.localDescription
}));
}, logError);
}
signalingChannel.onmessage = function (evt) {
if (!pc)
start();
var message = JSON.parse(evt.data);
if (message.sdp)
pc.setRemoteDescription(new RTCSessionDescription(message.sdp), function () {
// if we received an offer, we need to answer
if (pc.remoteDescription.type == 'offer')
pc.createAnswer(localDescCreated, logError);
}, logError);
else
pc.addIceCandidate(new RTCIceCandidate(message.candidate));
};
function logError(error) {
log(error.name + ': ' + error.message);
}
復(fù)制代碼
查看“單頁(yè)面”視頻聊天的例子simpl.info/pc.可以在 控制臺(tái)的lgo看到offer/answer 和candidate 的交換過(guò)程哨坪。如果你想了解更多,可以在Chrome瀏覽器打開(kāi) chrome://webrtc-internals 或在opera打開(kāi) opera://webrtc-internals下載完整的代碼乍楚。三.成員發(fā)現(xiàn)機(jī)制(Peer discovery)這里有個(gè)問(wèn)題: 我怎么發(fā)現(xiàn)誰(shuí)可以通話(huà)当编?對(duì)于電話(huà),我們有電話(huà)號(hào)碼和目錄徒溪。對(duì)于在線(xiàn)視頻聊天忿偷,我們需要身份和業(yè)務(wù)管理系統(tǒng)和一種讓用戶(hù)開(kāi)始會(huì)話(huà)的手段。WebRTC apps需要一種 讓客戶(hù)端標(biāo)示自己以便可以開(kāi)始和加入會(huì)話(huà)的方法臊泌。成員發(fā)現(xiàn)機(jī)制Peer discovery mechanisms沒(méi)有被WebRTC定義鲤桥,在這里我們不用做選擇。這個(gè)過(guò)程可以像發(fā)送一個(gè)URL地址這么簡(jiǎn)單渠概,對(duì)于視頻聊天應(yīng)用茶凳,比如 talky.io, tawk.com and browsermeeting.com嫂拴,你通過(guò)分享一個(gè)通用鏈接邀請(qǐng)別人進(jìn)入一個(gè)會(huì)話(huà)。開(kāi)發(fā)者Chris Ball開(kāi)發(fā)了一個(gè)有趣的實(shí)驗(yàn):serverless-webrtc贮喧,可以讓W(xué)ebRTC呼叫參與者分享元數(shù)據(jù)筒狠,通過(guò)任何信息服務(wù),比如IM箱沦,email或者信鴿辩恼。四.怎么創(chuàng)建一個(gè)signling服務(wù)?再說(shuō)一遍:信令機(jī)制沒(méi)有被WebRTC標(biāo)準(zhǔn)定義谓形,無(wú)論你選擇哪種 灶伊,你需要一個(gè)中間服務(wù)器去交換信令信息和不同客戶(hù)端間的應(yīng)用數(shù)據(jù)。慶幸的是寒跳,信令信息很小谁帕,大部分交換都是在通話(huà)開(kāi)始的時(shí)候。在測(cè)試 apprtc.appspot.com 和 samdutton-nodertc.jit.su 時(shí)冯袍,我們發(fā)現(xiàn)一個(gè) 視頻會(huì)話(huà)匈挖,總共有大概30-45的信息被信令服務(wù)器處理,信息大小大概是10kB康愤。除了相對(duì)要求不高的帶寬儡循,WebRTC 信令服務(wù)器不用花費(fèi)過(guò)多的內(nèi)存和進(jìn)程,因?yàn)橹恍枰D(zhuǎn)發(fā)信息和保持很少的會(huì)議狀態(tài)數(shù)據(jù)(比如那個(gè)客戶(hù)端被連接了)小貼士 :信令機(jī)制不僅可以用來(lái)交換會(huì)話(huà)元數(shù)據(jù)征冷,也能用來(lái)傳達(dá)應(yīng)用數(shù)據(jù)择膝。它就是個(gè)信息服務(wù)。五.從服務(wù)端推信息給客戶(hù)端一個(gè)信令服務(wù)器需要是雙向的:客戶(hù)端到服務(wù)器和服務(wù)器到客戶(hù)端检激。雙向通訊違反了HTTP 客戶(hù)端/服務(wù)端 請(qǐng)求/回復(fù)的模式肴捉,但是有一些發(fā)展多年的技術(shù),例如long polling(長(zhǎng)時(shí)間輪詢(xún)) 被用來(lái)從服務(wù)端發(fā)送數(shù)據(jù)給一個(gè)運(yùn)行中的web應(yīng)用叔收。最近齿穗,EventSource API 被廣泛的應(yīng)用,它允許“服務(wù)端發(fā)送事件”:數(shù)據(jù)通過(guò)HTTP從服務(wù)端發(fā)送給瀏覽器饺律。這里有個(gè)簡(jiǎn)單的demo:simpl.info/es窃页。EventSource被設(shè)計(jì)為一種消息傳送方式,但是它可以跟XHR 結(jié)合做成一個(gè)交換signaling的服務(wù):從一個(gè)呼叫者傳遞信息复濒,由XHR 請(qǐng)求傳遞脖卖,推送給被呼叫者。WebSocket 是一種更自然的解放方案巧颈,它是為了全雙工 客戶(hù)端-服務(wù)端通訊設(shè)計(jì)的(信息可以在同一時(shí)間在兩個(gè)端傳遞)畦木。用純WebSocket或者Server-Sent Events (EventSource) 做為signaling服務(wù)的優(yōu)點(diǎn)是后端調(diào)用這些APIs可以用多種Web框架實(shí)現(xiàn),在使用PHP,Python和Ruby的情況下砸泛。大約有四分之三的瀏覽器支持WebSocket ,更重要的是十籍,所有支持WebRTC的桌面瀏覽器和移動(dòng)瀏覽器都支持WebSocket蛆封。TLS(安全傳輸層協(xié)議)應(yīng)該用于所有的鏈接,已確保信息不會(huì)被截?cái)嗉宋怼M瑫r(shí)用proxy traversal減少問(wèn)題(更多關(guān)于WebSocket 和proxy traversal的資料可以看WebRTC chapter 和WebSocket Cheat Sheet)apprtc.appspot.com 的信令是通過(guò)Google App Engine Channel API完成的娶吞,Google App Engine Channel API是使用了Comet技術(shù)(長(zhǎng)時(shí)間輪詢(xún))讓APP后端和web客戶(hù)端 實(shí)現(xiàn)推送通訊功能垒迂。這里有個(gè)代碼預(yù)演械姻。另外一種方案,可以通過(guò)Ajax去輪詢(xún)服務(wù)端獲取signaling机断,但會(huì)導(dǎo)致一堆多余的網(wǎng)絡(luò)請(qǐng)求楷拳,特別是在移動(dòng)客戶(hù)端。在一個(gè)會(huì)話(huà)被確定后吏奸,用戶(hù)仍然需要去輪詢(xún)signaling信息欢揖,因?yàn)闀?huì)話(huà)可能會(huì)被其他用戶(hù)改變或者終止》芪担《WebRTC》這本書(shū)就用了這種經(jīng)過(guò)優(yōu)化輪詢(xún)頻率的方法她混。信令壓縮雖然一個(gè)信令服務(wù)器在每一個(gè)客戶(hù)端中花費(fèi)相當(dāng)小的帶寬和CPU,但是一個(gè)普遍使用的應(yīng)用可能需要從不同的地點(diǎn)處理很多信息泊碑,并且有很多高的并發(fā)數(shù)坤按。一個(gè)大流量的WebRTC 應(yīng)用需要心理服務(wù)端去處理相當(dāng)大的負(fù)荷。這里我們不講細(xì)節(jié)馒过,下面有一些 處理高數(shù)據(jù)量臭脓,高性能的信息通訊設(shè)置:1.XMPP,最初被稱(chēng)為Jabber:一種被開(kāi)發(fā)用來(lái)即時(shí)通訊的協(xié)議腹忽,可以用來(lái)做signaling来累。服務(wù)端可以用 ejabberd andOpenfire實(shí)現(xiàn)。JavaScript客戶(hù)端窘奏,例如 Strophe.js 使用BOSH去模仿雙向通訊流嘹锁,但因?yàn)?a target="_blank" rel="nofollow">各種原因,BOSH可能不像WebSocket那么有效率着裹。(Jingle 是一種支持視頻和語(yǔ)音的XMPP擴(kuò)展兼耀,WebRTC從libjingle庫(kù)(Jingle的C++實(shí)現(xiàn)庫(kù))里使用了網(wǎng)絡(luò)和傳輸組件 )2.像 ZeroMQ(據(jù)說(shuō)TokBox服務(wù)端使用了)、OpenMQ的開(kāi)源庫(kù)求冷。3.使用支持WebSocket商業(yè)的云服務(wù)平臺(tái)瘤运。4.商業(yè)的WebRTC 平臺(tái),比如vLine.開(kāi)發(fā)者Phil Leggetter提供了一系列信息服務(wù)器和第三方庫(kù)列表在Real-Time Web Technologies Guide匠题。用Node開(kāi)發(fā)基于Sockket.io的信令服務(wù)下面有個(gè)例子,Socket.io可以輕易創(chuàng)建一個(gè)用于交換信息的服務(wù)拯坟。Socket.io非常適合WebRTC 的信令,因?yàn)樗褪且浴皉ooms”的概念設(shè)計(jì)的韭山。這個(gè)demo不是一個(gè)產(chǎn)品級(jí)別的服務(wù)郁季,但是能夠應(yīng)付小數(shù)量的用戶(hù)冷溃。Socket.io通過(guò)下面的回調(diào)使用WebSocket: Adobe Flash Socket, AJAX long polling, AJAX multipart streaming, Forever Iframe and JSONP polling。Socket.io也被移植到后端版本梦裂,但是最廣為人知的是Node版本似枕。這個(gè)demo沒(méi)有WebRTC,它只是展示怎么創(chuàng)建一個(gè)webapp的signaling。用控制臺(tái)查看log年柠,去看下客戶(hù)端加入一個(gè)房間和交換數(shù)據(jù)發(fā)生了什么變化凿歼。WebRTC codelab會(huì)一步一步教你怎么整合這個(gè)demo變成一個(gè)完整的WEbRTC視頻聊天應(yīng)用。你可以從step 5 of the codelab repo下載源碼或者在samdutton-nodertc.jit.su運(yùn)行(用兩個(gè)瀏覽器打開(kāi)這個(gè)鏈接 )這是客戶(hù)端的index.htl:
var static = require('node-static');
var http = require('http');
var file = new(static.Server)();
var app = http.createServer(function (req, res) {
file.serve(req, res);
}).listen(2013);
var io = require('socket.io').listen(app);
io.sockets.on('connection', function (socket){
// convenience function to log server messages to the client
function log(){
var array = ['>>> Message from server: '];
for (var i = 0; i < arguments.length; i++) {
array.push(arguments[i]);
}
socket.emit('log', array);
}
socket.on('message', function (message) {
log('Got message:', message);
// for a real app, would be room only (not broadcast)
socket.broadcast.emit('message', message);
});
socket.on('create or join', function (room) {
var numClients = io.sockets.clients(room).length;
log('Room ' + room + ' has ' + numClients + ' client(s)');
log('Request to create or join room ' + room);
if (numClients === 0){
socket.join(room);
socket.emit('created', room);
} else if (numClients === 1) {
io.sockets.in(room).emit('join', room);
socket.join(room);
socket.emit('joined', room);
} else { // max two clients
socket.emit('full', room);
}
socket.emit('emit(): client ' + socket.id + ' joined room ' + room);
socket.broadcast.emit('broadcast(): client ' + socket.id + ' joined room ' + room);
});
});
復(fù)制代碼
要運(yùn)行這個(gè)app冗恨,你需要安裝Node, socket.io and node-static答憔。可以在 nodejs.org下載Node掀抹,再安裝 socket.io 和node-static虐拓,在終端運(yùn)行Node Package Manager:npm install socket.ionpm install node-static啟動(dòng)服務(wù),運(yùn)行下面命令node server.js在瀏覽器打開(kāi) localhost:2013.用新的瀏覽器打開(kāi)localhost:2013 傲武,用控制臺(tái)看下發(fā)生了什么使用 RTCDataChannel交換信息初始化一個(gè)WebRTC會(huì)話(huà)蓉驹,必須有一個(gè)信令 服務(wù)器。然而揪利,一旦兩端確定了 一個(gè)通話(huà)态兴,理論上,RTCDataChannel可以接替信令通道土童,這可以減少信號(hào)的延遲诗茎。一旦信息直接在兩端通訊,RTCDataChannel會(huì)幫忙減少帶寬使用和進(jìn)程開(kāi)銷(xiāo)献汗。沒(méi)有例子敢订,但可以看下面:信令性能和擴(kuò)展性1.RTCPeerConnection 不會(huì)搜集candidates,直到setLocalDescription() 被調(diào)用罢吃。這個(gè)被JSEP IETF draft.強(qiáng)制要求了楚午。2.利用Trickle ICE(看上面解釋?zhuān)航邮盏絚andidates后立即調(diào)用addIceCandidate(),現(xiàn)成的信令服務(wù) 這里有一些可以用的WebRTC signaling服務(wù)端:
webRTC.io: 第一個(gè)抽象庫(kù) for WebRTC.
easyRTC: 一個(gè)完整的WebRTC包 a full-stack WebRTC package.
Signalmaster:一個(gè)使用 SimpleWebRTCJavaScrip客戶(hù)端庫(kù)的signaling服務(wù)
如果你一點(diǎn)都不想編碼尿招,你可以用完整的商業(yè)WebRTC平臺(tái)矾柜,像vLine, OpenTok and Asterisk愛(ài)立信創(chuàng)建了一個(gè) signaling server using PHP on Apache,在WebRTC早期的時(shí)候就谜,現(xiàn)在這個(gè)已經(jīng)被棄用了怪蔑,但是如果你考慮到相似的情況,這個(gè)代碼還是值得一看的丧荐。六.Signaling安全
Security is the art of making nothing happen.
— Salman Rushdie
所有WebRTC 組件都被強(qiáng)制加密缆瓣。
但是信令機(jī)制沒(méi)有被WebRTC標(biāo)準(zhǔn)定義,所有確保信令安全取決于你虹统,如果一個(gè)攻擊者想去劫持信令弓坞,他們會(huì)導(dǎo)致會(huì)話(huà)中止隧甚,重定向鏈接和記錄渡冻,改變或者注入內(nèi)容宜雀。
一個(gè)牢固的信令最重要的功能是使用加密協(xié)議禀综,HTTPS 和WSS (i.e TLS)可以確保信息不會(huì)非加密攔截届氢。
同時(shí)寂祥,小心不要廣播信令信息惜犀,不然攻擊者可以使用相同的信令服務(wù)鏈接其他來(lái)電用戶(hù)刹缝。
使用 TLS.去確保WebRTC應(yīng)用的安全颂砸。
信令交互完之后碰缔,使用ICE去處理NATs和防火墻對(duì)于元數(shù)據(jù)的信令戳护,WebRTC應(yīng)用可以使用中間服務(wù)金抡,但實(shí)際的媒體和數(shù)據(jù)流在一個(gè)會(huì)話(huà)確立后,RTCPeerConnection 嘗試去直連客戶(hù)端:P2P在一個(gè)簡(jiǎn)單的世界里腌且,每一個(gè)WebRTC端都有一個(gè)唯一的地址梗肝,這樣他可以與其他端交換數(shù)據(jù),以便直接 通訊铺董。
也就是說(shuō):
STUN服務(wù)器用來(lái)獲取外部網(wǎng)絡(luò)地址。
如果P2P失敗的話(huà),[size=14.4444446563721px]TURN服務(wù)器用來(lái)中繼通訊计福。
每一個(gè)TURN服務(wù)器都支持STUN:一個(gè)TURN服務(wù)器是由一個(gè)STUN服務(wù)器加上中繼功能跌捆。ICE也可以用來(lái)應(yīng)付復(fù)雜的NAT設(shè)置:
事實(shí)上,NAT的”打洞“可能需要除了公共IP之外的端口地址象颖。
WebRTC應(yīng)用在iceServers配置對(duì)象(RTCPeerConnection constructor)里設(shè)置STUN and/or TURN服務(wù)器地址佩厚。
apprtc.appspot.com里這個(gè)值像這樣:
{
'iceServers': [
{
'url': 'stun:stun.l.google.com:19302'
},
{
'url': 'turn:192.158.29.39:3478?transport=udp',
'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
'username': '28224511:1379330808'
},
{
'url': 'turn:192.158.29.39:3478?transport=tcp',
'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
'username': '28224511:1379330808'
}
]
}
復(fù)制代碼
一旦RTCPeerConnection 有了這些信息,ICE會(huì)自動(dòng)啟動(dòng):RTCPeerConnection 使用ICE框架計(jì)算出兩端間最佳路線(xiàn)说订,需要STUN和TURN服務(wù)器抄瓦。
STUNNATs會(huì)給它的設(shè)備提供一個(gè)內(nèi)部網(wǎng)絡(luò)IP地址,但這個(gè)地址不能在外網(wǎng)使用陶冷,因?yàn)闆](méi)有外網(wǎng)的地址钙姊,所有WebRTC沒(méi)辦法做連接,為解決這個(gè)問(wèn)題埂伦,WebRTC使用了STUN煞额。STUN服務(wù)架設(shè)在外網(wǎng),它有一個(gè)簡(jiǎn)單的任務(wù):獲取一個(gè)發(fā)送請(qǐng)求的設(shè)備(運(yùn)行在NAT后邊的應(yīng)用)的IP和端口赤屋,然后返回這個(gè)地址立镶。換句話(huà)說(shuō)壁袄,應(yīng)用使用STUN服務(wù)器發(fā)現(xiàn)它的外網(wǎng)IP和端口类早,這個(gè)過(guò)程確保了一個(gè)WebRTC端獲得它自己的公共地址,然后通過(guò)signaling機(jī)制發(fā)送這個(gè)信息給另一端嗜逻,這樣就可以建立起一個(gè)直接連接涩僻。(在實(shí)際中,不同的NATs有不同的工作方式栈顷,可能有多個(gè)NAT層逆日,但是原理是一樣的)STUN服務(wù)器不需要做太多工作和存儲(chǔ)太多東西,所以簡(jiǎn)單的STUN服務(wù)器可以應(yīng)付大量的請(qǐng)求萄凤。根據(jù) webrtcstats.com的統(tǒng)計(jì)室抽,使用STUN方式建立WebRTC通話(huà)的成功率有86%的。
重述:TURN是在兩端間中轉(zhuǎn)視頻/語(yǔ)音/數(shù)據(jù) 流漾月,而不是發(fā)送數(shù)據(jù)病梢。
TURN 有個(gè)公共地址,所以每個(gè)端即使在防火墻或者代理后面梁肿,也能訪(fǎng)問(wèn)到蜓陌。
TURN有個(gè)簡(jiǎn)單的任務(wù)觅彰,中轉(zhuǎn)數(shù)據(jù)流,但不像STUN钮热,TURN會(huì)花費(fèi)大量帶寬缔莲。所有,TURN需要夠強(qiáng)壯霉旗。
圖表表示TURN的作用:?jiǎn)渭兊腟TUN不起作用痴奏,客戶(hù)端就會(huì)轉(zhuǎn)向使用TURN。
部署 STUN 和 TURN 服務(wù)器作為測(cè)試厌秒,谷歌公布了一個(gè)公共的STUN服務(wù)读拆,stun.l.google.com:19302栓袖, apprtc.appspot.com用的就是這個(gè)胁勺。作為一個(gè)產(chǎn)品級(jí)別的 STUN/TURN服務(wù)器,我們建議使用 rfc5766-turn-server逗威,STUN 和TURN的源碼可以從code.google.com/p/rfc5766-turn-server獲取蚌讼,這個(gè)鏈接也包括了部署的資料辟灰。A VM image for Amazon Web Services is also available.本社區(qū)也發(fā)布了部署教程:部署教程一個(gè)可代替的TURN服務(wù)器是restrund,可以在source code 下載到篡石,下面介紹在谷歌Compute Engine部署resrund的步驟:
Open firewall as necessary, for tcp=443, udp/tcp=3478
Create four instances, one for each public IP, Standard Ubuntu 12.06 image
Set up local firewall config (allow ANY from ANY)
Install tools:sudo apt-get install makesudo apt-get install gcc
Install libre from creytiv.com/re.html
Fetch restund from creytiv.com/restund.html and unpack
wget hancke.name/restund-auth.patch and apply with patch -p1 < restund-auth.patch
Run make, sudo make install for libre and restund
Adapt restund.conf to your needs (replace IP addresses and make sure it contains the same shared secret) and copy to /etc
Copy restund/etc/restund to /etc/init.d/
Configure restund:Set LD_LIBRARY_PATHCopy restund.conf to /etc/restund.confSet restund.conf to use the right 10. IP address
Run restund
Test using stund client from remote machine: ./client IP:port
七.突破p2p:多人會(huì)議WebRTC你可以需要看下Justin Uberti提議的IETF標(biāo)識(shí):請(qǐng)求TURN服務(wù)的API很容易想象到一些場(chǎng)景不只是一對(duì)一的視頻通話(huà)芥喇,舉個(gè)例子,公司小組需要一個(gè)視頻會(huì)議凰萨,或者一個(gè)公開(kāi)的演講继控,一個(gè)演講者面對(duì)數(shù)百(或者數(shù)千)的觀看者。一個(gè)WebRTC應(yīng)用可以使用多個(gè)RTCPeerConnections胖眷,這樣每一個(gè)端可以連接其他端形成一個(gè)網(wǎng)絡(luò)武通。talky.io就是使用這種方法實(shí)現(xiàn),對(duì)于少數(shù)的用戶(hù)珊搀,可以很好的工作冶忱。但是進(jìn)程和帶寬開(kāi)銷(xiāo)會(huì)非常大,特別是移動(dòng)客戶(hù)端境析。
大量用戶(hù)通話(huà)的更好解決方案是使用Multipoint Control Unit(MCU)。這是一個(gè)在大量參與者間分布媒體的橋接服務(wù)器。MCUs可以在一個(gè)視頻 會(huì)議里處理不同的分辨率朝刊,編解碼耀里,和幀速率。對(duì)于多端會(huì)議拾氓,有很多因素要考慮:最重要的是冯挎,從多個(gè)源里,怎么顯示多個(gè)視頻和混合音頻咙鞍。像 vLine 的云平臺(tái)也在致力于優(yōu)化傳輸路由房官。
你可以去買(mǎi)一個(gè)MCU硬件或者自己搭一個(gè)。
sipML5:一個(gè) 開(kāi)源的 JavaScript SIP 客戶(hù)端
jsSIP: JavaScript SIP庫(kù)
Phono: 開(kāi)源JavaScript phone API, 作為一個(gè)插件
Zingaya: 一個(gè)嵌入式電話(huà)部件
Twilio: 音頻和信息
Uberconference: 會(huì)議技術(shù)
sipML5 的開(kāi)發(fā)者也開(kāi)發(fā)了webrtc2sip的網(wǎng)關(guān)Tethr and Tropo have demonstrated a framework for disaster communications 'in a briefcase', using an OpenBTS cell to enable communications between feature phones and computers via WebRTC. Telephone communication without a carrier! 發(fā)現(xiàn)更多WebRTC codelab: 一步一步教你怎么打造一個(gè)視頻和文本聊天應(yīng)用含末,使用Socket.io Signaling服務(wù)猜拾。在Node上面跑。2013 Google I/O WebRTC presentation WebRTC領(lǐng)頭人Justin Uberti.
Chris Wilson 關(guān)于WebRTC的介紹:Introduction to WebRTC Apps.
WebRTC Book 這本書(shū)有很多關(guān)于數(shù)據(jù)佣盒、signaling挎袜、網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)的細(xì)節(jié)。
WebRTC and Signaling: What Two Years Has Taught Us:介紹為什么把signaling脫離出標(biāo)準(zhǔn)是個(gè)好主意
A Practical Guide to Building WebRTC Apps:提供很多WebRTC的技術(shù)和基礎(chǔ)建設(shè)信息。
WebRTC chapter 深入研究WebRTC的結(jié)構(gòu)盯仪,使用案例和性能紊搪。翻譯?http://www.html5rocks.com/en/tutorials/webrtc/infrastructure/
!WebRTC中文社區(qū)原創(chuàng)全景,轉(zhuǎn)載請(qǐng)注明出處耀石,謝謝,水平有限,部分意思可能不到位爸黄,建議參考英文原帖滞伟!
WebRTC 可以p2p視頻通話(huà)
但是...
WebRTC 仍然需要幾個(gè)服務(wù):
信令服務(wù): 使客戶(hù)端之間交換數(shù)據(jù)用來(lái)協(xié)調(diào)建立通話(huà)
NAT穿透服務(wù):應(yīng)付NATs和防火墻
這篇文章會(huì)教你怎么搭建信令服務(wù),和用STUN/TURN服務(wù)去做nat穿透炕贵。另外诗良,我們會(huì)解釋W(xué)ebRTC是怎么做到多端通話(huà)的。以及如何和VoIP/PSTN(電話(huà))建立通話(huà)鲁驶。
如果你對(duì)WebRTC還沒(méi)有基礎(chǔ)鉴裹,我們強(qiáng)烈建議你先看下Getting Started With WebRTC。
一.什么是信令服務(wù)(Signaling)钥弯?信令是一個(gè)協(xié)調(diào)溝通的過(guò)程径荔,為了讓一個(gè)WebRTC應(yīng)用發(fā)起一個(gè)“通話(huà)”,客戶(hù)端間需要交換以下信令信息:1.發(fā)起和關(guān)閉一個(gè)通話(huà)的控制信息脆霎;2.錯(cuò)誤信息总处;3.媒體元數(shù)據(jù),比如編碼解碼設(shè)置睛蛛,帶寬和媒體類(lèi)型鹦马;4.Key數(shù)據(jù),用于確保安全通訊忆肾;5.網(wǎng)絡(luò)數(shù)據(jù)荸频,比如主機(jī)在外網(wǎng)下的IP地址和端口】透裕客戶(hù)端的信令處理需要一種來(lái)回傳遞信息的方法旭从,這種機(jī)制沒(méi)有被WebRTC定義,你需要自己去創(chuàng)建它场仲。下面我們將描繪幾種構(gòu)建信令服務(wù)的方法和悦。在此之前,先講幾個(gè)概念……為什么WebRTC沒(méi)有定義信令渠缕?為了避免冗余和最大化兼容已經(jīng)確立的技術(shù)鸽素,WebRTC沒(méi)有指定信令的方法和協(xié)議。-------------------------------(WebRTC設(shè)計(jì)思想是完全指定和控制媒體層亦鳞,但是讓signaling層盡量脫離應(yīng)用馍忽,原因是不同的應(yīng)用可能會(huì)使用不同的協(xié)議棒坏,比如已經(jīng)存在的SIP或者Jingle呼叫協(xié)議等。這份協(xié)議中舵匾,需要交換的關(guān)鍵信息是多媒體會(huì)議的描述信息俊抵,包括在媒體層確定必要的傳輸方式和 媒體配置信息)------------------------------------------------JSEP的結(jié)構(gòu)同樣避免了讓瀏覽器保存狀態(tài)信息,如果讓瀏覽器成為一個(gè)保存信令狀態(tài)的機(jī)器坐梯,會(huì)出現(xiàn)一個(gè)問(wèn)題徽诲,就是每次當(dāng)頁(yè)面重載的時(shí)候,信令會(huì)丟失吵血。所以更好的方案是用服務(wù)器保存信令狀態(tài)谎替。
var configuration = {
'iceServers': [{
'url': 'stun:stun.example.org'
}]
};
var pc;
// call start() to initiate
function start() {
pc = new RTCPeerConnection(configuration);
// send any ice candidates to the other peer
pc.onicecandidate = function (evt) {
if (evt.candidate)
signalingChannel.send(JSON.stringify({
'candidate': evt.candidate
}));
};
// let the 'negotiationneeded' event trigger offer generation
pc.onnegotiationneeded = function () {
pc.createOffer(localDescCreated, logError);
}
// once remote stream arrives, show it in the remote video element
pc.onaddstream = function (evt) {
remoteView.src = URL.createObjectURL(evt.stream);
};
// get a local stream, show it in a self-view and add it to be sent
navigator.getUserMedia({
'audio': true,
'video': true
}, function (stream) {
selfView.src = URL.createObjectURL(stream);
pc.addStream(stream);
}, logError);
}
function localDescCreated(desc) {
pc.setLocalDescription(desc, function () {
signalingChannel.send(JSON.stringify({
'sdp': pc.localDescription
}));
}, logError);
}
signalingChannel.onmessage = function (evt) {
if (!pc)
start();
var message = JSON.parse(evt.data);
if (message.sdp)
pc.setRemoteDescription(new RTCSessionDescription(message.sdp), function () {
// if we received an offer, we need to answer
if (pc.remoteDescription.type == 'offer')
pc.createAnswer(localDescCreated, logError);
}, logError);
else
pc.addIceCandidate(new RTCIceCandidate(message.candidate));
};
function logError(error) {
log(error.name + ': ' + error.message);
}
復(fù)制代碼
查看“單頁(yè)面”視頻聊天的例子simpl.info/pc.可以在 控制臺(tái)的lgo看到offer/answer 和candidate 的交換過(guò)程。如果你想了解更多急但,可以在Chrome瀏覽器打開(kāi) chrome://webrtc-internals 或在opera打開(kāi) opera://webrtc-internals下載完整的代碼澎媒。三.成員發(fā)現(xiàn)機(jī)制(Peer discovery)這里有個(gè)問(wèn)題: 我怎么發(fā)現(xiàn)誰(shuí)可以通話(huà)?對(duì)于電話(huà)羊始,我們有電話(huà)號(hào)碼和目錄旱幼。對(duì)于在線(xiàn)視頻聊天,我們需要身份和業(yè)務(wù)管理系統(tǒng)和一種讓用戶(hù)開(kāi)始會(huì)話(huà)的手段突委。WebRTC apps需要一種 讓客戶(hù)端標(biāo)示自己以便可以開(kāi)始和加入會(huì)話(huà)的方法柏卤。成員發(fā)現(xiàn)機(jī)制Peer discovery mechanisms沒(méi)有被WebRTC定義,在這里我們不用做選擇匀油。這個(gè)過(guò)程可以像發(fā)送一個(gè)URL地址這么簡(jiǎn)單缘缚,對(duì)于視頻聊天應(yīng)用,比如 talky.io, tawk.com and browsermeeting.com敌蚜,你通過(guò)分享一個(gè)通用鏈接邀請(qǐng)別人進(jìn)入一個(gè)會(huì)話(huà)桥滨。開(kāi)發(fā)者Chris Ball開(kāi)發(fā)了一個(gè)有趣的實(shí)驗(yàn):serverless-webrtc,可以讓W(xué)ebRTC呼叫參與者分享元數(shù)據(jù)弛车,通過(guò)任何信息服務(wù)齐媒,比如IM,email或者信鴿纷跛。四.怎么創(chuàng)建一個(gè)signling服務(wù)喻括?再說(shuō)一遍:信令機(jī)制沒(méi)有被WebRTC標(biāo)準(zhǔn)定義,無(wú)論你選擇哪種 贫奠,你需要一個(gè)中間服務(wù)器去交換信令信息和不同客戶(hù)端間的應(yīng)用數(shù)據(jù)唬血。慶幸的是望蜡,信令信息很小,大部分交換都是在通話(huà)開(kāi)始的時(shí)候拷恨。在測(cè)試 apprtc.appspot.com 和 samdutton-nodertc.jit.su 時(shí)脖律,我們發(fā)現(xiàn)一個(gè) 視頻會(huì)話(huà),總共有大概30-45的信息被信令服務(wù)器處理腕侄,信息大小大概是10kB小泉。除了相對(duì)要求不高的帶寬,WebRTC 信令服務(wù)器不用花費(fèi)過(guò)多的內(nèi)存和進(jìn)程兜挨,因?yàn)橹恍枰D(zhuǎn)發(fā)信息和保持很少的會(huì)議狀態(tài)數(shù)據(jù)(比如那個(gè)客戶(hù)端被連接了)小貼士 :信令機(jī)制不僅可以用來(lái)交換會(huì)話(huà)元數(shù)據(jù)膏孟,也能用來(lái)傳達(dá)應(yīng)用數(shù)據(jù)。它就是個(gè)信息服務(wù)拌汇。五.從服務(wù)端推信息給客戶(hù)端一個(gè)信令服務(wù)器需要是雙向的:客戶(hù)端到服務(wù)器和服務(wù)器到客戶(hù)端柒桑。雙向通訊違反了HTTP 客戶(hù)端/服務(wù)端 請(qǐng)求/回復(fù)的模式,但是有一些發(fā)展多年的技術(shù)噪舀,例如long polling(長(zhǎng)時(shí)間輪詢(xún)) 被用來(lái)從服務(wù)端發(fā)送數(shù)據(jù)給一個(gè)運(yùn)行中的web應(yīng)用魁淳。最近,EventSource API 被廣泛的應(yīng)用与倡,它允許“服務(wù)端發(fā)送事件”:數(shù)據(jù)通過(guò)HTTP從服務(wù)端發(fā)送給瀏覽器界逛。這里有個(gè)簡(jiǎn)單的demo:simpl.info/es。EventSource被設(shè)計(jì)為一種消息傳送方式纺座,但是它可以跟XHR 結(jié)合做成一個(gè)交換signaling的服務(wù):從一個(gè)呼叫者傳遞信息息拜,由XHR 請(qǐng)求傳遞,推送給被呼叫者净响。WebSocket 是一種更自然的解放方案少欺,它是為了全雙工 客戶(hù)端-服務(wù)端通訊設(shè)計(jì)的(信息可以在同一時(shí)間在兩個(gè)端傳遞)。用純WebSocket或者Server-Sent Events (EventSource) 做為signaling服務(wù)的優(yōu)點(diǎn)是后端調(diào)用這些APIs可以用多種Web框架實(shí)現(xiàn)馋贤,在使用PHP,Python和Ruby的情況下赞别。大約有四分之三的瀏覽器支持WebSocket ,更重要的是,所有支持WebRTC的桌面瀏覽器和移動(dòng)瀏覽器都支持WebSocket配乓。TLS(安全傳輸層協(xié)議)應(yīng)該用于所有的鏈接仿滔,已確保信息不會(huì)被截?cái)唷M瑫r(shí)用proxy traversal減少問(wèn)題(更多關(guān)于WebSocket 和proxy traversal的資料可以看WebRTC chapter 和WebSocket Cheat Sheet)apprtc.appspot.com 的信令是通過(guò)Google App Engine Channel API完成的犹芹,Google App Engine Channel API是使用了Comet技術(shù)(長(zhǎng)時(shí)間輪詢(xún))讓APP后端和web客戶(hù)端 實(shí)現(xiàn)推送通訊功能崎页。這里有個(gè)代碼預(yù)演。另外一種方案腰埂,可以通過(guò)Ajax去輪詢(xún)服務(wù)端獲取signaling实昨,但會(huì)導(dǎo)致一堆多余的網(wǎng)絡(luò)請(qǐng)求,特別是在移動(dòng)客戶(hù)端盐固。在一個(gè)會(huì)話(huà)被確定后荒给,用戶(hù)仍然需要去輪詢(xún)signaling信息,因?yàn)闀?huì)話(huà)可能會(huì)被其他用戶(hù)改變或者終止刁卜≈镜纾《WebRTC》這本書(shū)就用了這種經(jīng)過(guò)優(yōu)化輪詢(xún)頻率的方法。信令壓縮雖然一個(gè)信令服務(wù)器在每一個(gè)客戶(hù)端中花費(fèi)相當(dāng)小的帶寬和CPU蛔趴,但是一個(gè)普遍使用的應(yīng)用可能需要從不同的地點(diǎn)處理很多信息挑辆,并且有很多高的并發(fā)數(shù)。一個(gè)大流量的WebRTC 應(yīng)用需要心理服務(wù)端去處理相當(dāng)大的負(fù)荷孝情。這里我們不講細(xì)節(jié)鱼蝉,下面有一些 處理高數(shù)據(jù)量,高性能的信息通訊設(shè)置:1.XMPP箫荡,最初被稱(chēng)為Jabber:一種被開(kāi)發(fā)用來(lái)即時(shí)通訊的協(xié)議魁亦,可以用來(lái)做signaling。服務(wù)端可以用 ejabberd andOpenfire實(shí)現(xiàn)羔挡。JavaScript客戶(hù)端洁奈,例如 Strophe.js 使用BOSH去模仿雙向通訊流,但因?yàn)?a target="_blank" rel="nofollow">各種原因绞灼,BOSH可能不像WebSocket那么有效率利术。(Jingle 是一種支持視頻和語(yǔ)音的XMPP擴(kuò)展,WebRTC從libjingle庫(kù)(Jingle的C++實(shí)現(xiàn)庫(kù))里使用了網(wǎng)絡(luò)和傳輸組件 )2.像 ZeroMQ(據(jù)說(shuō)TokBox服務(wù)端使用了)低矮、OpenMQ的開(kāi)源庫(kù)印叁。3.使用支持WebSocket商業(yè)的云服務(wù)平臺(tái)。4.商業(yè)的WebRTC 平臺(tái)军掂,比如vLine.開(kāi)發(fā)者Phil Leggetter提供了一系列信息服務(wù)器和第三方庫(kù)列表在Real-Time Web Technologies Guide轮蜕。用Node開(kāi)發(fā)基于Sockket.io的信令服務(wù)下面有個(gè)例子,Socket.io可以輕易創(chuàng)建一個(gè)用于交換信息的服務(wù)。Socket.io非常適合WebRTC 的信令良姆,因?yàn)樗褪且浴皉ooms”的概念設(shè)計(jì)的肠虽。這個(gè)demo不是一個(gè)產(chǎn)品級(jí)別的服務(wù),但是能夠應(yīng)付小數(shù)量的用戶(hù)玛追。Socket.io通過(guò)下面的回調(diào)使用WebSocket: Adobe Flash Socket, AJAX long polling, AJAX multipart streaming, Forever Iframe and JSONP polling税课。Socket.io也被移植到后端版本,但是最廣為人知的是Node版本痊剖。這個(gè)demo沒(méi)有WebRTC,它只是展示怎么創(chuàng)建一個(gè)webapp的signaling韩玩。用控制臺(tái)查看log,去看下客戶(hù)端加入一個(gè)房間和交換數(shù)據(jù)發(fā)生了什么變化陆馁。WebRTC codelab會(huì)一步一步教你怎么整合這個(gè)demo變成一個(gè)完整的WEbRTC視頻聊天應(yīng)用找颓。你可以從step 5 of the codelab repo下載源碼或者在samdutton-nodertc.jit.su運(yùn)行(用兩個(gè)瀏覽器打開(kāi)這個(gè)鏈接 )這是客戶(hù)端的index.htl:
var http = require('http');
var file = new(static.Server)();
var app = http.createServer(function (req, res) {
file.serve(req, res);
}).listen(2013);
var io = require('socket.io').listen(app);
io.sockets.on('connection', function (socket){
// convenience function to log server messages to the client
function log(){
var array = ['>>> Message from server: '];
for (var i = 0; i < arguments.length; i++) {
array.push(arguments[i]);
}
socket.emit('log', array);
}
socket.on('message', function (message) {
log('Got message:', message);
// for a real app, would be room only (not broadcast)
socket.broadcast.emit('message', message);
});
socket.on('create or join', function (room) {
var numClients = io.sockets.clients(room).length;
log('Room ' + room + ' has ' + numClients + ' client(s)');
log('Request to create or join room ' + room);
if (numClients === 0){
socket.join(room);
socket.emit('created', room);
} else if (numClients === 1) {
io.sockets.in(room).emit('join', room);
socket.join(room);
socket.emit('joined', room);
} else { // max two clients
socket.emit('full', room);
}
socket.emit('emit(): client ' + socket.id + ' joined room ' + room);
socket.broadcast.emit('broadcast(): client ' + socket.id + ' joined room ' + room);
});
});
復(fù)制代碼
要運(yùn)行這個(gè)app,你需要安裝Node, socket.io and node-static叮贩』魇ǎ可以在 nodejs.org下載Node佛析,再安裝 socket.io 和node-static,在終端運(yùn)行Node Package Manager:npm install socket.ionpm install node-static啟動(dòng)服務(wù)彪蓬,運(yùn)行下面命令node server.js在瀏覽器打開(kāi) localhost:2013.用新的瀏覽器打開(kāi)localhost:2013 寸莫,用控制臺(tái)看下發(fā)生了什么使用 RTCDataChannel交換信息初始化一個(gè)WebRTC會(huì)話(huà),必須有一個(gè)信令 服務(wù)器档冬。然而膘茎,一旦兩端確定了 一個(gè)通話(huà),理論上酷誓,RTCDataChannel可以接替信令通道披坏,這可以減少信號(hào)的延遲。一旦信息直接在兩端通訊盐数,RTCDataChannel會(huì)幫忙減少帶寬使用和進(jìn)程開(kāi)銷(xiāo)棒拂。沒(méi)有例子,但可以看下面:信令性能和擴(kuò)展性1.RTCPeerConnection 不會(huì)搜集candidates娘扩,直到setLocalDescription() 被調(diào)用着茸。這個(gè)被JSEP IETF draft.強(qiáng)制要求了。2.利用Trickle ICE(看上面解釋?zhuān)航邮盏絚andidates后立即調(diào)用addIceCandidate()琐旁,現(xiàn)成的信令服務(wù) 這里有一些可以用的WebRTC signaling服務(wù)端:webRTC.io: 第一個(gè)抽象庫(kù) for WebRTC.
easyRTC: 一個(gè)完整的WebRTC包 a full-stack WebRTC package.
Signalmaster:一個(gè)使用 SimpleWebRTCJavaScrip客戶(hù)端庫(kù)的signaling服務(wù)
如果你一點(diǎn)都不想編碼涮阔,你可以用完整的商業(yè)WebRTC平臺(tái),像vLine, OpenTok and Asterisk愛(ài)立信創(chuàng)建了一個(gè) signaling server using PHP on Apache灰殴,在WebRTC早期的時(shí)候敬特,現(xiàn)在這個(gè)已經(jīng)被棄用了,但是如果你考慮到相似的情況牺陶,這個(gè)代碼還是值得一看的伟阔。六.Signaling安全 Security is the art of making nothing happen.
— Salman Rushdie
所有WebRTC 組件都被強(qiáng)制加密。
但是信令機(jī)制沒(méi)有被WebRTC標(biāo)準(zhǔn)定義掰伸,所有確保信令安全取決于你皱炉,如果一個(gè)攻擊者想去劫持信令,他們會(huì)導(dǎo)致會(huì)話(huà)中止狮鸭,重定向鏈接和記錄合搅,改變或者注入內(nèi)容。
一個(gè)牢固的信令最重要的功能是使用加密協(xié)議歧蕉,HTTPS 和WSS (i.e TLS)可以確保信息不會(huì)非加密攔截灾部。
同時(shí),小心不要廣播信令信息惯退,不然攻擊者可以使用相同的信令服務(wù)鏈接其他來(lái)電用戶(hù)赌髓。
使用 TLS.去確保WebRTC應(yīng)用的安全。
信令交互完之后,使用ICE去處理NATs和防火墻對(duì)于元數(shù)據(jù)的信令锁蠕,WebRTC應(yīng)用可以使用中間服務(wù)夷野,但實(shí)際的媒體和數(shù)據(jù)流在一個(gè)會(huì)話(huà)確立后,RTCPeerConnection 嘗試去直連客戶(hù)端:P2P在一個(gè)簡(jiǎn)單的世界里匿沛,每一個(gè)WebRTC端都有一個(gè)唯一的地址扫责,這樣他可以與其他端交換數(shù)據(jù),以便直接 通訊逃呼。
STUN服務(wù)器用來(lái)獲取外部網(wǎng)絡(luò)地址队丝。
如果P2P失敗的話(huà)靡馁,[size=14.4444446563721px]TURN服務(wù)器用來(lái)中繼通訊。
每一個(gè)TURN服務(wù)器都支持STUN:一個(gè)TURN服務(wù)器是由一個(gè)STUN服務(wù)器加上中繼功能机久。ICE也可以用來(lái)應(yīng)付復(fù)雜的NAT設(shè)置:
事實(shí)上臭墨,NAT的”打洞“可能需要除了公共IP之外的端口地址。
WebRTC應(yīng)用在iceServers配置對(duì)象(RTCPeerConnection constructor)里設(shè)置STUN and/or TURN服務(wù)器地址膘盖。
apprtc.appspot.com里這個(gè)值像這樣:
{
'iceServers': [
{
'url': 'stun:stun.l.google.com:19302'
},
{
'url': 'turn:192.158.29.39:3478?transport=udp',
'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
'username': '28224511:1379330808'
},
{
'url': 'turn:192.158.29.39:3478?transport=tcp',
'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
'username': '28224511:1379330808'
}
]
}
復(fù)制代碼
一旦RTCPeerConnection 有了這些信息胧弛,ICE會(huì)自動(dòng)啟動(dòng):RTCPeerConnection 使用ICE框架計(jì)算出兩端間最佳路線(xiàn),需要STUN和TURN服務(wù)器衔憨。
STUNNATs會(huì)給它的設(shè)備提供一個(gè)內(nèi)部網(wǎng)絡(luò)IP地址叶圃,但這個(gè)地址不能在外網(wǎng)使用,因?yàn)闆](méi)有外網(wǎng)的地址践图,所有WebRTC沒(méi)辦法做連接掺冠,為解決這個(gè)問(wèn)題,WebRTC使用了STUN。STUN服務(wù)架設(shè)在外網(wǎng)德崭,它有一個(gè)簡(jiǎn)單的任務(wù):獲取一個(gè)發(fā)送請(qǐng)求的設(shè)備(運(yùn)行在NAT后邊的應(yīng)用)的IP和端口斥黑,然后返回這個(gè)地址。換句話(huà)說(shuō)眉厨,應(yīng)用使用STUN服務(wù)器發(fā)現(xiàn)它的外網(wǎng)IP和端口锌奴,這個(gè)過(guò)程確保了一個(gè)WebRTC端獲得它自己的公共地址,然后通過(guò)signaling機(jī)制發(fā)送這個(gè)信息給另一端憾股,這樣就可以建立起一個(gè)直接連接鹿蜀。(在實(shí)際中,不同的NATs有不同的工作方式服球,可能有多個(gè)NAT層茴恰,但是原理是一樣的)STUN服務(wù)器不需要做太多工作和存儲(chǔ)太多東西,所以簡(jiǎn)單的STUN服務(wù)器可以應(yīng)付大量的請(qǐng)求斩熊。根據(jù) webrtcstats.com的統(tǒng)計(jì)往枣,使用STUN方式建立WebRTC通話(huà)的成功率有86%的。
TURN 有個(gè)公共地址,所以每個(gè)端即使在防火墻或者代理后面箫攀,也能訪(fǎng)問(wèn)到肠牲。
TURN有個(gè)簡(jiǎn)單的任務(wù),中轉(zhuǎn)數(shù)據(jù)流靴跛,但不像STUN缀雳,TURN會(huì)花費(fèi)大量帶寬。所有梢睛,TURN需要夠強(qiáng)壯肥印。
圖表表示TURN的作用:?jiǎn)渭兊腟TUN不起作用,客戶(hù)端就會(huì)轉(zhuǎn)向使用TURN绝葡。
部署 STUN 和 TURN 服務(wù)器作為測(cè)試深碱,谷歌公布了一個(gè)公共的STUN服務(wù),stun.l.google.com:19302藏畅, apprtc.appspot.com用的就是這個(gè)敷硅。作為一個(gè)產(chǎn)品級(jí)別的 STUN/TURN服務(wù)器,我們建議使用 rfc5766-turn-server,STUN 和TURN的源碼可以從code.google.com/p/rfc5766-turn-server獲取绞蹦,這個(gè)鏈接也包括了部署的資料力奋。A VM image for Amazon Web Services is also available.本社區(qū)也發(fā)布了部署教程:部署教程一個(gè)可代替的TURN服務(wù)器是restrund,可以在source code 下載到幽七,下面介紹在谷歌Compute Engine部署resrund的步驟:Open firewall as necessary, for tcp=443, udp/tcp=3478
Create four instances, one for each public IP, Standard Ubuntu 12.06 image
Set up local firewall config (allow ANY from ANY)
Install tools:sudo apt-get install makesudo apt-get install gcc
Install libre from creytiv.com/re.html
Fetch restund from creytiv.com/restund.html and unpack
wget hancke.name/restund-auth.patch and apply with patch -p1 < restund-auth.patch
Run make, sudo make install for libre and restund
Adapt restund.conf to your needs (replace IP addresses and make sure it contains the same shared secret) and copy to /etc
Copy restund/etc/restund to /etc/init.d/
Configure restund:Set LD_LIBRARY_PATHCopy restund.conf to /etc/restund.confSet restund.conf to use the right 10. IP address
Run restund
Test using stund client from remote machine: ./client IP:port
七.突破p2p:多人會(huì)議WebRTC你可以需要看下Justin Uberti提議的IETF標(biāo)識(shí):請(qǐng)求TURN服務(wù)的API很容易想象到一些場(chǎng)景不只是一對(duì)一的視頻通話(huà)景殷,舉個(gè)例子攀芯,公司小組需要一個(gè)視頻會(huì)議褒脯,或者一個(gè)公開(kāi)的演講衫生,一個(gè)演講者面對(duì)數(shù)百(或者數(shù)千)的觀看者屋谭。一個(gè)WebRTC應(yīng)用可以使用多個(gè)RTCPeerConnections,這樣每一個(gè)端可以連接其他端形成一個(gè)網(wǎng)絡(luò)并巍。talky.io就是使用這種方法實(shí)現(xiàn)咐扭,對(duì)于少數(shù)的用戶(hù)子寓,可以很好的工作梁厉。但是進(jìn)程和帶寬開(kāi)銷(xiāo)會(huì)非常大,特別是移動(dòng)客戶(hù)端踏兜。
你可以去買(mǎi)一個(gè)MCU硬件或者自己搭一個(gè)尊搬。
jsSIP: JavaScript SIP庫(kù)
Phono: 開(kāi)源JavaScript phone API, 作為一個(gè)插件
Zingaya: 一個(gè)嵌入式電話(huà)部件
Twilio: 音頻和信息
Uberconference: 會(huì)議技術(shù)
sipML5 的開(kāi)發(fā)者也開(kāi)發(fā)了webrtc2sip的網(wǎng)關(guān)Tethr and Tropo have demonstrated a framework for disaster communications 'in a briefcase', using an OpenBTS cell to enable communications between feature phones and computers via WebRTC. Telephone communication without a carrier! 發(fā)現(xiàn)更多WebRTC codelab: 一步一步教你怎么打造一個(gè)視頻和文本聊天應(yīng)用,使用Socket.io Signaling服務(wù)娱两。在Node上面跑莺匠。2013 Google I/O WebRTC presentation WebRTC領(lǐng)頭人Justin Uberti.Chris Wilson 關(guān)于WebRTC的介紹:Introduction to WebRTC Apps.
WebRTC Book 這本書(shū)有很多關(guān)于數(shù)據(jù)、signaling十兢、網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)的細(xì)節(jié)趣竣。
WebRTC and Signaling: What Two Years Has Taught Us:介紹為什么把signaling脫離出標(biāo)準(zhǔn)是個(gè)好主意
A Practical Guide to Building WebRTC Apps:提供很多WebRTC的技術(shù)和基礎(chǔ)建設(shè)信息。
WebRTC chapter 深入研究WebRTC的結(jié)構(gòu)旱物,使用案例和性能遥缕。