WebRTC通信流程
git地址:
https://webrtc.googlesource.com/src
下面这张图清楚的描述了WebRTC的协议分层,该图引自《web性能权威指南》,如有侵权,立马删掉。
下面我们就一点点来剖析WebRTC。
传输层协议
WebRTC实时通信传输音视频的场景,讲究的是实时,当下,处理音频和视频流的应用一定要补偿间歇性的丢包,所以实时性的需求是大于可靠性的需求的。
如果使用TCP当传输层协议的话,如果中间出现丢包的情况,那么后续的所有的包都会被缓冲起来,因为TCP讲究可靠、有序,如果不清楚的朋友可以去看我上一篇关于TCP的内容讲解,web知识梳理。而UDP则正好相反,它只负责有什么消息我就传过去,不负责安全,不负责有没有到达,不负责交付顺序,这里从底层来看是满足WebRTC的需求的,所以WebRTC是采用UDP来当它的传输层协议的。
当然这里UDP只是作为传输层的基础,想要真正的达到WebRTC的要求,我们就要来分析在传输层之上,WebRTC做了哪些操作,用了哪些协议,来达到WebRTC的要求了。
RTCPeerConnection通道
RTCPeerConnection代表一个由本地计算机到远端的WebRTC连接。
该接口提供了创建,保持,监控,关闭连接的方法的实现,简而言之就是代表了端到端之间的一条通道。api调用上面代码里已经看到了,接下来我们就一点点的来剖析这条通道都用了哪些协议。
P2P内网穿透
上面我们也提到了UDP其实只是在IP层的基础上做了一些简单封装而已。而WebRTC如果要实现端到端的通信效果的话,必定要面临端到端之间很多层防火墙,NAT设备阻隔这些一系列的问题。之前我试过写了原生的webrtc 发现只要不在同一段局域网下面,经常会出现掉线连不上的情况。相同的道理这里就需要做 NAT 穿透处理了。
NAT穿透是啥,在讲NAT穿透之前我们需要先提几个概念:
公有IP地址是在Internet上全局唯一的IP地址,仅有一个设备可能拥有公有IP地址。
私有IP地址是非全局的唯一的IP地址,可能同时存在于很多不同的设备上。私有IP地址永远不会直接连接到internet。那私有IP地址的设备如何访问网络呢?
就是这个NAT(NetWork Address Translation),它允许单个设备(比如路由器)充当Internet(公有IP)和专有网络(私有IP)之间的代理。所以我们就可以通过这个NAT来处理很多层防火墙后那个设备是私有IP的问题。
路通了,那么就有另一个问题了,两个WebRTC客户端之间,大概率会存在A不知道B的可以直接发送到的IP地址和端口,B也不知道A的,那么又该如何通信呢?
这就要说到ICE了,也就是交互式连接建立。ICE允许WebRTC克服显示网络复杂性的框架,找到连接同伴的最佳途径并连接起来。
在大多数的情况下,ICE将会使用STUN服务器,其实使用的是在STUN服务器上运行的STUN协议,它允许客户端发现他们的公共IP地址以及他们所支持的NAT类型,所以理所当然STUN服务器必须架设在公网上。在大多数情况下,STUN服务器仅在连接设置期间使用,并且一旦建立该会话,媒体将直接在客户端之间流动。
具体过程让我们来看图会更清楚,WebRTC两个端各自有一个STUN服务器,通过STUN服务器来设置连接,一旦建立连接会话,媒体数据就可以直接在两个端之间流动。
刚才也说了大多数的情况,如果发生STUN服务器无法建立连接的情况的话,ICE将会使用TURN中继服务器,TURN是STUN的扩展,它允许媒体遍历NAT,而不会执行STUN流量所需的“一致打孔”,TURN服务器实际上在WebRTC对等体之间中继媒体,所以我这里理解的话使用TURN就很难被称为端对端之间通信了。
同样,我们画个图来形容TURN中继服务器的数据流动方式:
TURN 是在任何网络中为两端提供连接的最可靠方式,但现实情况下运维 TURN 服务器的投入也很大。因此,最好在其他直连手段都失败的情况下,再使用 TURN。 所以一般情况下每个WebRTC解决方案都会准备好支持这两种服务类型,并设计为处理TURN服务器上的处理要求。
————————————————
版权声明:本文为CSDN博主「jieqiang3」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/jieqiang3/article/details/89604025
WebRTC是HTML5支持的重要特性之一,有了它,不再需要借助音视频相关的客户端,直接通过浏览器的Web页面就可以实现音视频对聊功能。而且WebRTC项目是开源的,我们可以借助WebRTC源码快速构建自己的音视频对聊功能。无论是使用前端JS的WebRTC API接口,还是在WebRTC源码上构建自己的对聊框架,都需要遵循以下执行流程:
上述序列中,WebRTC并不提供Stun服务器和Signal服务器,服务器端需要自己实现。Stun服务器可以用google提供的实现stun协议的测试服务器(stun:stun.l.google.com:19302),Signal服务器则完全需要自己实现了,它需要在ClientA和ClientB之间传送彼此的SDP信息和candidate信息,ClientA和ClientB通过这些信息建立P2P连接来传送音视频数据。由于网络环境的复杂性,并不是所有的客户端之间都能够建立P2P连接,这种情况下就需要有个relay服务器做音视频数据的中转,本文本着源码剖析的态度,这种情况就不考虑了。这里说明一下, stun/turn、relay服务器的实现在WebRTC源码中都有示例,真是个名副其实的大宝库。
上述序列中,标注的场景是ClientA向ClientB发起对聊请求,调用描述如下:
- ClientA首先创建PeerConnection对象,然后打开本地音视频设备,将音视频数据封装成MediaStream添加到PeerConnection中。
- ClientA调用PeerConnection的CreateOffer方法创建一个用于offer的SDP对象,SDP对象中保存当前音视频的相关参数。ClientA通过PeerConnection的SetLocalDescription方法将该SDP对象保存起来,并通过Signal服务器发送给ClientB。
- ClientB接收到ClientA发送过的offer SDP对象,通过PeerConnection的SetRemoteDescription方法将其保存起来,并调用PeerConnection的CreateAnswer方法创建一个应答的SDP对象,通过PeerConnection的SetLocalDescription的方法保存该应答SDP对象并将它通过Signal服务器发送给ClientA。
- ClientA接收到ClientB发送过来的应答SDP对象,将其通过PeerConnection的SetRemoteDescription方法保存起来。
- 在SDP信息的offer/answer流程中,ClientA和ClientB已经根据SDP信息创建好相应的音频Channel和视频Channel并开启Candidate数据的收集,Candidate数据可以简单地理解成Client端的IP地址信息(本地IP地址、公网IP地址、Relay服务端分配的地址)。
- 当ClientA收集到Candidate信息后,PeerConnection会通过OnIceCandidate接口给ClientA发送通知,ClientA将收到的Candidate信息通过Signal服务器发送给ClientB,ClientB通过PeerConnection的AddIceCandidate方法保存起来。同样的操作ClientB对ClientA再来一次。
- 这样ClientA和ClientB就已经建立了音视频传输的P2P通道,ClientB接收到ClientA传送过来的音视频流,会通过PeerConnection的OnAddStream回调接口返回一个标识ClientA端音视频流的MediaStream对象,在ClientB端渲染出来即可。同样操作也适应ClientB到ClientA的音视频流的传输。
相关资料:
https://www.jianshu.com/p/c84be6f3ddf3
https://developer.aliyun.com/article/243480
https://bloggeek.me/best-webrtc-book/,这里介绍了5本书。
https://rtcdeveloper.com/t/topic/14040 Android 端如何使用 WebRTC
https://webrtc.github.io/webrtc-org/native-code/ Andriod端native开发
https://www.html5rocks.com/en/tutorials/webrtc/basics/ 不错的guide
转自:http://www.cnblogs.com/fangkm/p/4364553.html
还没有评论,来说两句吧...