webrtc简介
示例
webrtc提供一个标准用于在两个端点之间进行数据传送,本文以浏览器端RTCPeerConnection对webrtc实现来说明
以下是一个简单的示例(typescript),通过datachannel来传递数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| function getCandidate(pc: RTCPeerConnection){ return new Promise<RTCIceCandidate>((resolve, reject)=>{ pc.onicecandidate = (ev)=>{ if(ev.candidate){ resolve(ev.candidate) } } }) }
let pc1 = new RTCPeerConnection()
let pc2 = new RTCPeerConnection()
pc2.ondatachannel = (chan)=>{ chan.channel.send("hello"); }
let chan = pc1.createDataChannel("test") chan.onmessage = (ev)=>{ console.log(`${ev.data} world`) }
pc1.onicecandidate = (ev)=>{ if(ev.candidate){ pc2.addIceCandidate(ev.candidate) } }
let task1 = getCandidate(pc1)
let sdp1 = await pc1.createOffer()
pc1.setLocalDescription(sdp1)
let task2 = getCandidate(pc2)
pc2.setRemoteDescription(sdp1) pc2.addIceCandidate(await task1)
let sdp2 = await pc2.createAnswer()
pc2.setLocalDescription(sdp2) let candidate = await task2
pc1.setRemoteDescription(sdp2) pc1.addIceCandidate(candidate)
|
说明
1.端点之间是对等的,不论是谁先创建sdp或是后应答都是一样的
2.每个端点需要设置本地sdp与远程sdp
3.添加地址需要在设置远端sdp后
4.应答sdp需要先设置远程sdp
5.webrtc是p2p的,连接不能一对多
5.添加视频与音频track
1 2 3 4
| let stream = await navigator.mediaDevices.getUserMedia() for(let track of stream.getTracks()){ pc1.addTrack(track) }
|
问题
1.两个端点之间是怎么样交换sdp与candidate
以上的例子中因为两个端点都在可以互相访问,可以直接设置。但实际是需要一个公共服务器(Signal Server),通过与这个服务器建立连接来交换sdp及candidate
2.端点之间如何互通
创建sdp时,会获取当前端点的candidate(可以认为是一个地址,通过ice获得),之后将candidate通过Signal Server发送给另一个端点,远程端点可以通过这个地址直接访问
ice是什么
ice是一个框架主要包含了(stun,turn),ice属于p2p的一部分,是为了统一nat穿透的解决方案,RTCPeerConnection参数可以设置使用哪种穿透技术,不需要可以不设置
为什么sdp中不包含candidate
传统sdp的是包含candidate的,但是获取candidate可能会费时,所以webrtc采用trickle ice,并行sdp的创建与candidate的获取来节省时间,所以需要分开发送