由WebRTC谈起
本篇主要介绍笔者在iOS开发中使用WebRTC实现音视频通话功能涉及的相关技术,主要包括:
1)Socket
2)WebSocket
3)WebRTC
4)HTTP
5)SocketRocket
主要为相关的理论知识,后续笔者会补上相应的Demo。如有疑问欢迎留言探讨。
原生支持: iOS13开始,使用URLSessionWebSocketTask类可实现像发送HTTP请求一样的WebSocket功能。如果要对Web套接字(包括客户端和服务器支持)进行较低级别的控制,请查看Network框架:https://developer.apple.com/documentation/network。
一、Socket
是对TCP/IP 协议的封装,本质并不是一个协议,是应用层与 TCP/IP 协议族通信的中间软件抽象层(类似于对底层的封装),它是一组接口,让你在使用的时候更方便操作。
二、WebSocket协议
是HTML5下一种新的协议,也是基于TCP的一种网络协议,它实现了浏览器/客户端与服务器全双工(full-duplex)通信——连接成功以后允许服务器或客户端的任何一方主动发送信息给对方。WebSocket协议由两部分组成:握手和数据传输。Websocket是一个持久化的协议,只需要一次成功的HTTP握手,服务端会一直保留握手成功时的信息,直到客户端或服务端关闭请求。
创建了WebSocket后,会有一个HTTP请求发送到服务器以发起连接。取得服务器响应后,建立的连接使用HTTP升级,从HTTP协议交换为WebSocket协议。WebSocket使用了自定义的协议,未加密的连接不再是http://,而是ws://,默认端口为80;加密的连接也不是https://,而是wss://,默认端口为443。即,使用标准的HTTP服务器无法实现WebSocket,只有支持WebSocket协议的服务器才能正常工作。一旦WebSocket连接建立后,后续数据都以帧序列的形式传输。
WebSocket协议的特点包括:
(1)建立在 TCP 协议之上。
(2)与 HTTP 协议有着良好的兼容性。握手阶段采用 HTTP 协议,默认端口也是80和443,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。如何体现通信高效?WebSocket通信格式没有HTTP协议那么多的固定报头,且不用重复建立连接。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。(什么是同源限制?协议相同,域名相同,端口相同。目的是为了保证用户信息的安全,防止恶意的网站窃取数据。)
(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
(7)WebSocket通信协议于2011年被IETF定为标准RFC 6455,WebSocket API被W3C定为标准。
WebSocket如何实现长链接?创建了WebSocket后,会有一个HTTP请求发送到服务器以发起连接。取得服务器响应后,建立的连接使用HTTP升级,从HTTP协议交换为WebSocket协议。只需要一次成功的HTTP握手,服务端会一直保留握手成功时的信息,直到客户端或服务端关闭请求。WebSocket之所以能持久连接原因是它运行在TCP协议上,TCP协议自身是长连接协议,所以WebSocket当然可以长连接啦。
WebSocket如何管理连接?RFC6455-5.5意见稿指明:WebSocket协议定义了Control Frame 控制帧。WebSocket的控制帧有:Close、Ping、Pong。
Close帧:发起关闭请求;
Ping帧:通信发起方确认链路是否畅通的报文;
Pong帧:通信接收方回应链路是否畅通的报文。
WebSocket在建立连接之后,通信的基本数据帧格式如下图(来源RFC6455-5.2)没有Http协议那么多固定的报头,且不用重复建立连接,所以通信效率高:
WebSocket连接的生命周期:
WebSocket连接的生命周期
CONNECTING:使用Http发起请求,RFC6455-4(https://tools.ietf.org/html/rfc6455#section-4)规定了Client和Server的报文格式。Server在响应时使用Http状态码是101(切换协议)。在握手时,WebSocket连接处于CONNECTING状态。
OPEN:握手成功之后,进入OPEN状态。
CLOSING:如果一方发起了CLOSE帧,那么便标志着WebSocket连接进入了CLOSING状态;
CLOSED:当TCP连接关闭之后,那么WebSocet连接便进入了CLOSED状态。
三、WebRTC
名称源自网页实时通信(Web Real-Time Communication)的缩写,是谷歌2010年以6820万美元收购Global IP Solutions公司而获得的一项技术,由Google、Mozilla和Opera等支持的、免费的开放式项目。通过简单的API为浏览器和移动应用程序提供跨平台的音视频实时通信(RTC:Real-Time Communications )功能。WebRTC使得开发者在浏览器无需安装任何插件就可以实现音视频通信。
WebRTC提供了跨平台的音视频核心技术,包括音视频的采集、编解码、网络传输、显示等功能,支持的平台:Windows、Linux、Mac、Android及iOS。RTCPeerConnection是用于进行WebRTC调用以流式传输视频和音频以及交换数据的API,WebRTC使用RTCPeerConnection(对等连接)在浏览器之间传递流数据,但也需要一种协调通信和发送控制消息的机制,这一过程称为信令。信令处理过程需要客户端之间来回传递消息,这个过程在WebRTC里面是没有实现的,需要自己创建。即WebRTC未指定信令方法和协议,需要开发者确保使用安全协议。所有WebRTC组件都必须进行加密,即WebRTC是安全的(如何保证安全?)。WebRTC这种技术可以让开发者的精力集中在用户体验上而不是媒体流本身,因为API就会处理好媒体引擎的相关工作。
WebRTC 1.0 的重点是提供给开发者更多对媒体、数据通道的控制。而根据此前的提案(见后面的提案连接)显示,下一版本的 WebRTC 将有可能使数据处理脱离主线程。使用 RTCDataChannels 传输数据,相比使用 WebSocket 会有更好的拥塞控制。(该段内容笔者未确认)
参考连接:http://www.sohu.com/a/275427719_458408
提案连接:https://www.w3.org/2011/04/webrtc/wiki/images/5/5c/WebRTCWG-2018-06-19.pdf
如何保证安全:当连通性检测完成后,WebRTC会开启DTLS(Datagram TLS)握手,用于协商出SRTP中加密RTP包的对称秘钥。该过程称为DTLS-SRTP,保证了数据传输的安全性。
参考:https://imweb.io/topic/5a4a6cb2a192c3b460fce37f
RTP/RTCP 和 SRTP/SRTCP协议是什么?参考:https://blog.csdn.net/thinkerleo1997/article/details/80233530
基本概念:
SDP: 即会话描述协议(Session Description Protocol ),主要保存当前会话的媒体和传输信息,其中媒体信息包括媒体类型、传输协议、媒体格式等,传输信息包括媒体的远程地址信息、带宽等;它由多行KV格式的文本信息组成,具体可参考这里(https://tools.ietf.org/pdf/draft-nandakumar-rtcweb-sdp-08.pdf)。WebRTC通过信令建立一个SDP握手的过程,只有通过SDP握手,双方才知道对方的信息,这是建立p2p通道的基础。
Offer: 通信的发起方对自己的sdp描述
Answer: 通信的接收方对自己的sdp描述
信令:协商通信过程,传递基本的数据信息,其中包括SDP描述信息、会话控制信息(节点加入、退出及各类的业务控制信息等)、网络信息、错误信息等。是指控制建立连接和断开连接的状态的数据。在建立连接之前,信令必须发生在带外(通过服务器),但一旦建立连接,就可以通过已经建立的通道发送更新信令(如挂断)。(这里要了解一下什么叫“带外(OOB:Out-Of-Band)”,百度百科:https://baike.baidu.com/item/out-of-band/15801641?fr=aladdin)
OOB概述:传输层协议使用带外数据(out-of-band,OOB)来发送一些重要的数据,如果通信一方有重要的数据需要通知对方时,协议能够将这些数据快速地发送到对方。为了发送这些数据,协议一般不使用与普通数据相同的通道,而是使用另外的通道。linux系统的套接字机制支持低层协议发送和接受带外数据。但是TCP协议没有真正意义上的带外数据。为了发送重要协议,TCP提供了一种称为紧急模式(urgent mode)的机制。TCP协议在数据段中设置URG位,表示进入紧急模式。接收方可以对紧急模式采取特殊的处理。很容易看出来,这种方式数据不容易被阻塞,并且可以通过在我们的服务器端程序里面捕捉SIGURG信号来及时接受数据。
信令通道:与服务端建立连接和断开连接的通道,对于WebRTC而言就是信令通道。
为了建立一个WebRTC的通讯过程,客户端需要交换如下信息:
a)会话控制信息,用来开始和结束通话,即开始视频、结束视频这些操作指令。
b)处理错误的消息。
c)元数据,如各自的音视频解码方式、带宽。
d)网络数据,对方的公网IP与端口、内网IP与端口。
STUN服务器:是用来取外网地址的。
TURN服务器:是在P2P失败时进行转发的,中继转发。
STUN和TURN服务器的作用主要处理打洞与转发,配合完成ICE协议。
ICE:Interactive Connectivity Establishment,交互式连接建立。
WebRTC通信
基于WebRTC的点对点音视频通信流程如下:
1)客户端A初始化本地音视频设备,创建一个用于Offer的SDP对象,该对象中保存当前音视频的相关信息;
2)客户端A通过信令服务器将SDP信息发送给客户端B;
3)客户端B接收到A的SDP信息后保存,初始化本地音视频设备并创建用于Answer的SDP对象;
4)客户端B通过信令服务器将SDP信息发送给客户端A;
5)客户端A、B通过交换SDP等信息,建立P2P通道进行音视频传输;
示意图如下图所示:
WebRTC ICE(交互式连接建立)(ICE:Interactive Connectivity Establishment)
以下是呼叫信令期间发生的消息交换的高级过程,即:WebRTC 信令交互流程图:
************************************************开始************************************************
##关键词
--[SOMETHING]-->:表示从主叫方发送给被叫方的“SOMETHING”类型的消息。另一解释是:主叫方所要执行操作。
<--[SOMETHING]--:表示从被叫方发送给主叫方的“SOMETHING”类型的消息。另一解释是:被叫方所要执行的操作。
SS(Signal Service):通过服务器发送的信息(通过BCM 服务器发送的信息)
DC(Data Channel):通过WebRTC数据通道发送的消息
### Message Exchange / State Flow Overview (消息交换/状态流概述)
| Caller(主叫方) | Callee(被叫方) |
+----------------------------+-------------------------+
开始拨出电话:`handleOutgoingCall`...
--[SS.CallOffer]-->
…并开始生成iceCandidate候选,先保存在本地。iceCandidate里面包含了SDP、公网地址、用来标识当前ice中流媒体的id(sdpMid),这个公网地址是由STUN、TURN Server发过来的。
当生成iceCandidate候选后,将会调用方法`handleLocalAddedIceCandidate` ,并把这些iceCandidate保存起来。
被叫方收到来电,通过 `handleReceivedOffer` 发送呼叫应答
<--[SS.CallAnswer]--
1. 开始生成iceCandidate候选。
2. 立即通过`handleLocalAddedIceCandidate` 将它们发送给主叫方。
<--[SS.ICEUpdate]-- (多次发送)
主叫方收到应答后调用方法: `handleReceivedAnswer`,接着发送所有前面保存的iceCandidate候选 (在此之后生成的iceCandidate候选会立即发送)
--[SS.ICEUpdates]--> (多次发送)
完成交换iceCandidate候选后…(此时表示双方身份已确认,接下来会通过P2P通道建立音视频会话,这里会涉及NAT技术,有可能失失败。如果失败,主叫方会一直显示呼叫中,被叫方不会显示任何界面)双方都调用方法: `handleIceConnected`
显示远程铃声用户界面
1.连接到提供的数据通道
2.显示来电界面
3.如果被叫人接听电话
4.发送连接消息
<--[DC.ConnectedMesage]--
接收到的连接消息后显示呼叫已连接。
主叫方挂断(被叫方同样可以挂断)调用方法:
--[DC.Hangup]-->
--[SS.Hangup]-->
************************************************结束************************************************
上面的消息交换可以整理为如下的简化版的WebRTC建立连接过程:
简化版的WebRTC建立连接过程1)主叫方通过 createOffer 生成 SDP 描述
2)主叫方通过 setLocalDescription,设置本地的描述信息
3)主叫方将 offer SDP 发送给被叫方
4)被叫方通过 setRemoteDescription,设置远端的描述信息
5)被叫方通过 createAnswer 创建出自己的 SDP 描述
6)被叫方通过 setLocalDescription,设置本地的描述信息
7)被叫方将 anwser SDP 发送给主叫方
8)主叫方通过 setRemoteDescription,设置远端的描述信息。
只有通过SDP握手,双方才知道对方的信息,这是建立p2p通道的基础。 通过SDP握手后,客户端之间就会建立起一个点对点的直接通讯通道。但是由于我们所处的网络环境错综复杂,用户可能处在私有内网内,使用p2p传输时,将会遇到NAT(网络地址转换)以及防火墙等阻碍。这个时候我们就需要在SDP握手时,通过STUN/TURN/ICE相关NAT穿透技术(也有称为打洞或穿墙技术)来保障p2p链接的建立。
WebRTC的视频部分,包含采集、编解码(I420/VP8)、加密、媒体文件、图像处理、显示、网络传输与流控(RTP/RTCP)等功能。
视频采集支持多种媒体类型,比如I420、YUY2、RGB、UYUY等,并可以进行帧大小和帧率控制。
WebRTC采用I420/VP8编解码技术。VP8是Google收购ON2后的开源实现,并且也用在WebM项目中。VP8能以更少的数据提供更高质量的视频,特别适合视频会议这样的需求。
视频加密是WebRTC的video_engine一部分,相当于视频应用层面的功能,给点对点的视频双方提供了数据上的安全保证,可以防止在Web上视频数据的泄漏。
视频加密在发送端和接收端进行加解密视频数据,密钥由视频双方协商,代价是会影响视频数据处理的性能;也可以不使用视频加密功能,这样在性能上会好些。
视频加密的数据源可能是原始的数据流,也可能是编码后的数据流。估计是编码后的数据流,这样加密代价会小一些,需要进一步研究。
WebRTC的音频部分,包含设备、编解码(iLIBC/iSAC/G722/PCM16/RED/AVT、NetEQ)、加密、声音文件、声音处理、声音输出、音量控制、音视频同步、网络传输与流控(RTP/RTCP)等功能。
WebRTC采用iLIBC/iSAC/G722/PCM16/RED/AVT编解码技术。
WebRTC还提供NetEQ功能---抖动缓冲器及丢包补偿模块,能够提高音质,并把延迟减至最小。
另外一个核心功能是基于语音会议的混音处理。
声音处理针对音频数据进行处理,包括回声消除(AEC)、AECM(AEC Mobile)、自动增益(AGC)、降噪(NS)、静音检测(VAD)处理等功能,用来提升声音质量。
丢包补偿原理是什么?
自动增益(AGC:Automatic Gain Control)概念?
TCP协议:属于传输层,是可靠的、面向连接的。主要解决如何在IP层之上可靠地传递数据包,使得网络上接收端收到发送端所发出的所有包,并且顺序与发送顺序一致。TCP连接的建立依靠“三次握手”,而释放则需要“四次握手”。
IP协议:属于网络层,主要解决网络路由和寻址问题。
Http协议:属于应用层协议,一个简单的请求-响应协议,是一种无状态、非持久的协议,是被动性的,也就是只能客户端发起。服务端不保留上一次与客户端交互时的任何状态,每次都要重新传输 identity info (鉴别信息),来告诉服务端你是谁。HTTP的长连接和短连接本质上是TCP长连接和短连接。HTTP1.1支持keep-alive。
Http与WebSocket区别与联系
(1)Http与WebSocket是两个完全不同的协议,都是基于TCP的。两者唯一的联系是WebSocket利用Http进行握手;具体说明请看:RFC6455-1.7(https://tools.ietf.org/html/rfc6455#section-5.5)
(2)WS默认也使用80端口;WSS默认也使用443端口。
(3)Http协议局限性一大堆,比如明文传输、无法保证信息完整性、没有身份验证等。而WebSocket的出现则是为了解决Http协议只能由Client发起通信请求的问题。WebSocket是全双工通信。
(4)HTTP是运行在TCP协议传输层上的应用协议,而WebSocket是通过HTTP协议协商如何连接,然后独立运行在TCP协议传输层上的应用协议。
WebSocket仅仅是利用了HTTP协议做连接请求。WebSocket相当于一个简化版的TCP传输子层(实际上WebSocket也是应用层协议)。WebSocket之所以能持久连接原因是它运行在TCP协议上,TCP协议自身是长连接协议,所以WebSocket当然可以长连接啦。如果你要问为什么HTTP不是长连接,原因是早期的HTTP在发起每个请求,响应完成后就会关闭Socket。但是后来加了多路复用KeepAlive协议后HTTP协议已经可以实现长连接了,可以处理长连接事务了。至于添加WebSocket特性,是为了更好、更灵活,轻量的与服务器通讯。因为WebSocket提供了简单的消息规范,可以更快的适应长连接的环境,其实现在HTTP协议自身就可以做,但是不太轻便,因为HTTP是一种无状态、非持久的协议,是被动性的,也就是只能客户端发起。服务端不保留上一次与客户端交互时的任何状态,每次都要重新传输 identity info (鉴别信息),来告诉服务端你是谁,每次请求和应答都带有完整的Http头,占用网络传输带宽,增加了每次传输的数据量。为什么HTML4不支持WebSocket?原因是WebSocket的协商机制HTML4底层API没有实现。
WebSocket与Socket是没什么关系的
WebSocket协议和Http协议:都是基于TCP的,所以他们都是可靠的协议,是在应用层。
Socket:是对TCP/IP 协议的封装,本质并不是一个协议,是应用层与 TCP/IP 协议族通信的中间软件抽象层(类似于对底层的封装),它是一组接口,让你在使用的时候更方便操作。
WebSocket与WebRTC(Web Real-Time Communication)是什么关系?
WebSocket:是WebRTC的基础,为WebRTC负责客服端发现和数据转发。
TCP协议:参考https://blog.csdn.net/Awille/article/details/79748193
SocketRocket:Facebook的开源框架
WebRTC开发和VoIP开发之间有什么区别与联系?
待完善知识点:WebRTC移动端兼容性检测,如何配置MediaStreamConstraints, 信令(iceCandidate, sessionDescription)传输方式的选择,iceCandidate和sessionDescription设置的先后顺序,STUN和TURN的概念,如何实现截图及录制视频及上传图片和视频功能,如何高效跟踪错误?
WebRTC拥塞控制和码率调节策略是怎么样的?在弱网环境下如何保证图像不失真?
猜:好像是改RTCRtpEncodingParameters这个类里的ssrc参数。是改采样频率?
参考资料:
WebRTC百科:https://baike.baidu.com/item/WebRTC/5522744?fr=aladdin
WebRTC基础知识:https://webrtc.org.cn/category/basic/
GoogleWebRTC-pod安装文档:https://cocoapods.org/pods/GoogleWebRTC
GoogleWebRTC-iOS官网:https://webrtc.org/native-code/ios/