前言
这个星期碰到公司同事有项目是需要做对讲功能,但听说一直以来都是调用的第三方SDK
。听到这类需求首先想到是webRTC
相关的开发。
虽然之前有过一段时间想去了解,但碍于webRTC
里出现的概念对于传统的web
开发来说比较陌生以及也没有实际的开发需要,所以中途都放弃了。
但未来可能会有这种需求,那就借此机会来稍微弄清webRTC
是建立P2P
的连接的机制。
正文
流程图
以下是根据peerjs
源码,梳理的webRTC
在建立连接时的流程图:
flowchart TD step1[创建RTCPeerConnection] step2[peerConnection创建DataChannel] step3[peerConnection创建offer] step4[把offer设为localDescription] step5[触发icecandidate] step6[把candidate通过socket发送给peer] step7[把offer通过socket发送给peer] step8[peer接收offer] step9[peer把offer里的sdp设为remoteDescription] step10[peer创建answer] step11[peer把answer设为localDescription] step12[peer把answer通过socket发送回来] step13[peer进行addIceCandidate] step14[把peer的answer设为remoteDescription] step15[peer触发icecandidate] step16[peer把candidate通过socket发送回来] step17[进行addIceCandiate] step1-->step2 step2-->step3 step3-->step4 step4--2-->step5 step5-->step6 step4--1-->step7 step7-->step8 step8-->step9 step9-->step10 step10-->step11 step11--1-->step12 step11--2-->step15 step15-->step16 step16-->step17 step12-->step14 step6-->step13
术语:
transport address
在RFC
文档中指代ip
地址和port
STUN(Session Traversal Utilities for NAT)
服务器的主要作用是帮助client
获取其对应的经NAT
转换后的public transport address
TURN(Traversal Using Relays Around NAT)
服务器的主要作用是给peerA
,分配一个relayed transport address
,让peerB
通过发送数据到这个地址后,TURN
服务器再转发给peerB
。TURN
可以解决STUN
无法处理的Symmetric NAT
类型。Symmetric NAT
是指NAT
会因请求方的transport address
或接收方的transport address
不同,而给请求方映射不同的public transport address
。因为目标地址不一,所以peerB
不能使用与STUN
服务器收到的server-reflexive transport address
相同的地址与peerA
通信。
需要signaling
服务的原因
由于RTCConnection
未建立前并不知道对方的transport address
,所以需要开发者先通过任意signaling
服务作中介(服务的实现方式不作限定,常见的是通过websocket
)来交换各自session description
和ice candidate
。
sd格式
session description
包含己方将要传输的媒体信息(地址、端口、格式等),是一个多行key=value
格式的文本。
STUN/TURN
服务器的作用
在setLocalDescription
后,会请求STUN/TURN
服务器来获得peer
可以直接通信的transport address
,生成candidate
的配置后触发icecandidate
事件,。把candiate
通过signaliing
服务发给peer
,让对方把这个连接候选方式,添加到peerConnection
中。
candidate
生成结束
当某一轮的candidate
生成完毕后,icecandidate
事件会回调一个空的candiate
来标志生成完毕,如果连接建立成功iceconnectionstatechange
,peerConnection
的iceConnectionState
会变为connected
。
candidate
的类型:
1.host
:直连,peer
的真实地址
2.srflx
:server-reflexive
,发送STUN Binding Request
到STUN
服务器后,经NAT
转换过的public
地址
3.prflx
:peer-flexive
,发送STUN Binding Request
到peer
后,从peer
获得的经NAT
转换过的public
地址
4.relay
:TURN
服务的中继地址
webRTC
会按规则选取最优的candidate
进行连接。
总结
本文只是简单地梳理了webRTC
建立连接过程发生的事情,但也可以看到其实webRTC
(先不论存在relay
的情况)跟一般的request/response
的模式差别不太大,服务方都会通过server-reflexive
的transport address
传数据给client
,可能因为使用的是udp
,实时性会更好些。所以如果只是单方面的视频推流,感觉是不太需要用到webRTC
的,webRTC
的主要使用场景应该是数据实时互传方面的。