webrtc简介

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)
}
}
})
}

// 创建端点1
let pc1 = new RTCPeerConnection()
//创建端点2
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)
//端点1创建sdp
let sdp1 = await pc1.createOffer()
//端点1设置本地sdp
pc1.setLocalDescription(sdp1)


let task2 = getCandidate(pc2)
//端点2设置端点1的sdp
pc2.setRemoteDescription(sdp1)
pc2.addIceCandidate(await task1)
//端点2创建应答sdp
let sdp2 = await pc2.createAnswer()
//端点2设置本地sdp
pc2.setLocalDescription(sdp2)
let candidate = await task2

//端点1设置端点2的sdp
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的获取来节省时间,所以需要分开发送