在常规的视频通讯中,人们往往需要借助第三方服务器作为中转,比如甲乙两人想要通过视频通信,那么他们需要分别和第三方服务器建立信道,甲和服务器建立一个信道,乙和服务器建立一个信道。这样一来,双方的视频流畅度就会受到和第三方服务器之间的信道带宽的限制,当多人视频时,通讯效率会受到很大的局限。人们希望有一个不借助第三方服务器而能够点对点直接传输视频数据协议,于是有了WebRTC。 WebRTC,名称源自网页实时通信(英语:Web Real-Time Communication)的缩写,是一个支持网页浏览器进行实时语音对话或视频对话的API。它于2011年6月1日开源并在Google、Mozilla基金会、Opera支持下被包括进万维网联盟的W3C推荐标准。 WebRTC主要有如下组件
WebRTC主要实现了三大类接口:
MediaStream
:通过MediaStream的API能够通过设备的摄像头及话筒获得视频、音频的同步流RTCPeerConnection
:RTCPeerConnection是WebRTC用于构建点对点之间稳定、高效的流传输的组件RTCDataChannel
:RTCDataChannel使得浏览器之间(点对点)建立一个高吞吐量、低延时的信道,用于传输任意数据这三类接口主要负责三大方向: – MediaStream
负责获取本机的音视频流 – RTCPeerConnection
负责建立有效稳定的点对点连接 – RTCDataChannel
负责传输数据
想要建立一个WebRTC连接,需要完成上面三个步骤,下面分别来看具体的实现步骤。
想要访问本机摄像头和麦克风,需要获取本机MediaStream
1 2 3 4 5 6 7 8 9 |
var streamToAttach; navigator.webkitGetUserMedia({ audio: true, video: true }, function (stream) { video.src = webkitURL.createObjectURL(stream); streamToAttach = stream; }, function(error) { alert(error); }); |
而Firefox下接口名称不同:
1 2 3 4 5 6 7 8 9 10 |
code code="javascript"> var streamToAttach; navigator.mozGetUserMedia({ audio: true, video: true }, function (stream) { video.mozSrcObject = stream; video.play(); streamToAttach = stream; }, function(error) { alert(error); }); </code> |
WebRTC使用PeerConnection接口来建立点对点连接 首先我们先建立一个Peer
1 2 3 4 5 |
var peerConnection = new webkitRTCPeerConnection( { "iceServers": [{ "url": "stun:stun.l.google.com:19302" }] } ); |
我们可以使用Google的STUN服务器: stun:stun.l.google.com:19302
Firefox下使用mozRTCPeerConnection
然后设置peer对象的事件处理函数:
1 2 3 4 5 |
peerConnection.onicecandidate = onicecandidate; peerConnection.onaddstream = onaddstream; peerConnection.addStream (streamToAttach); |
作为视频请求发起者,发出视频请求:
<
pre>
peerConnection.createOffer(function (sessionDescription) { peerConnection.setLocalDescription(sessionDescription);</p>
<pre><code>// 把自己的SDP信息发送给对方
}, function(error) { alert(error); }, { ‘mandatory’: { ‘OfferToReceiveAudio’: true, ‘OfferToReceiveVideo’: true } });
作为应答者,则需要处理请求者的SDP并发送自己的应答SDP:
1 2 3 |
peerConnection.setRemoteDescription(new RTCSessionDescription(offerSDP)); |
创建应答SDP:
peerConnection.createAnswer(function (sessionDescription) { peerConnection.setLocalDescription(sessionDescription);
// 将应答SDP送回请求者
}, function(error) { alert(error); }, { ‘mandatory’: { ‘OfferToReceiveAudio’: true, ‘OfferToReceiveVideo’: true } });
请求者收到应答SDP后:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
peerConnection.setRemoteDescription(new RTCSessionDescription(answerSDP)); </pre></p> <p><p></code></p> <h3>RTCDataChannel</h3> <p>我们可以使用RTCDataChannel传输数据,<code>DataChannel</code>是建立在<code>PeerConnection</code>上的,不能单独使用。 可以通过在peer对象上调用createDataCHannel方法创建一个RTCDataChannel并打上标签:</p> <pre><code code="javascript"> channel = pc.createDataCHannel("someLabel"); |
DataChannel使用方式几乎和WebSocket一样,有几个事件:
同时它有几个状态,可以通过 readyState 获取:
两个暴露的方法:
由于WebRTC在建立连接过程中,会向对方发送本地地址SDP,因此可以通过访问SDP获得访问者的IP:
1 2 3 4 5 6 7 8 9 |
<html> <body> Local description: <div id="localdescription"> </body> </html |
访问后效果如图: 红框即访问者当前内网ip。
einaros则给了个更漂亮的PoC,不仅获取访问者内网ip,还是用javascript扫描内网其他存活主机(点这里):