WebRTC学习总结

WebRTC (Web Real-Time Communications) 是一项实时通信技术,它容许网络应用或者站点,在不借助中间媒介的状况下,创建浏览器之间点对点(Peer-to-Peer)的链接,实现视频流和(或)音频流或者其余任意数据的传输。WebRTC包含的这些标准使用户在无需安装任何插件或者第三方的软件的状况下,建立点对点(Peer-to-Peer)的数据分享和电话会议成为可能。javascript

本篇文章从自身实践出发,结合相关代码,总结WebRTC实现的基本流程。java

1. 引言

首先咱们先看《WebRTC权威指南》上给出的流程图,从这张图,咱们要明确两件事:git

  • 第一,通讯双方须要先经过服务器交换一些信息
  • 第二,完成信息交换后,通讯双方将直接进行链接以传输数据

而后咱们再介绍一下WebRTC中的专有名词,方便读者对下文的理解。github

  • RTCPeerConnection:核心对象,每个链接对象都须要新建该对象
  • SDP(Session Description Protocol,会话描述协议):包含创建链接的一些必要信息,好比IP地址等,sdpRTCPeerConnection对象方法建立,咱们目前不须要知道该对象中的具体内容,使用黑盒传输便可
  • ICE(Interactive Connectivity Establishment,交互式链接创建技术):用户之间创建链接的方式,用来选取用户之间最佳的链接方式

2. WebRTC实现流程

如下代码不能直接运行,由于我这里并无实现信令服务器,如何实现信令服务器可自由选择(好比,socket.io、websocket等)。web

首先发起方获取视频流,若是成功,则新建RTCPeerConnection对象,而后建立offer,并发送给应答方。数组

  • addStream方法将getUserMedia方法中获取的流(stream)添加到RTCPeerConnection对象中,以进行传输
  • onaddStream事件用来监听通道中新加入的流,经过e.stream获取
  • onicecandidate事件用来寻找合适的ICE
  • createOffer()RTCPeerConnection对象自带的方法,用来建立offer,建立成功后调用setLocalDescription方法将localDescription设置为offerlocalDescription即为咱们须要发送给应答方的sdp
  • sendOffersendCandidate方法是自定义方法,用来将数据发送给服务器
// 引入<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>脚本
// 提高浏览器兼容性
var localConnection
var constraints={
    audio:false,
    video:true
}
navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError)
function handleSuccess(stream) {
  document.getElementById("video").srcObject = stream
  localConnection=new RTCPeerConnection()
  localConnection.addStream(stream)
  localConnection.onaddstream=function(e) {
    console.log('得到应答方的视频流' + e.stream)
  }
  localConnection.onicecandidate=function(event){
    if(event.candidate){
        sendCandidate(event.candidate)
    }
  }
  localConnection.createOffer().then((offer)=>{
    localConnection.setLocalDescription(offer).then(sendOffer)
  })
}
复制代码

一样的,接收方也须要新建一个RTCPeerConnection对象浏览器

var remoteConnection
var constraints={
    audio:false,
    video:true
    }
}
navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError)
function handleSuccess(stream) {
  document.getElementById("video").srcObject = stream
  remoteConnection=new RTCPeerConnection()
  remoteConnection.addStream(stream)
  remoteConnection.onaddstream=function(e) {
    console.log('得到发起方的视频流' + e.stream)
  }
  remoteConnection.onicecandidate=function(event){
      if(event.candidate){
          sendCandidate(event.candidate)
      }
  }
}
复制代码

当应答方收到发起方发送的offer以后,调用setRemoteDescription设置RTCPeerConnection对象的remoteDescription属性,设置成功以后调用createAnswer方法,建立answer成功以后将其设置为localDescription,而后把answer发送给服务器服务器

let desc=new RTCSessionDescription(sdp)
remoteConnection.setRemoteDescription(desc).then(function() {
    remoteConnection.createAnswer().then((answer)=>{
        remoteConnection.setLocalDescription(answer).then(sendAnswer)
    })
})
复制代码

当发起方收到应答方发送的answer以后,将其设置为remoteDescription,至此WebRTC链接完成。websocket

let desc=new RTCSessionDescription(sdp)
localConnection.setRemoteDescription(desc).then(()=>{console.log('Peer Connection Success')})
复制代码

此时虽然WebRTC链接已经完成,可是通讯双方还不能直接通讯,由于发送的ICE尚未处理,通讯双方尚未肯定最优的链接方式。网络

应答方收到发起方发送的ICE数据时,调用RTCPeerConnection对象的addIceCandidate方法。

remoteConnection.addIceCandidate(new RTCIceCandidate(ice))
复制代码

发起方收到应答方发送的ICE数据时,一样调用RTCPeerConnection对象的addIceCandidate方法。

localConnection.addIceCandidate(new RTCIceCandidate(ice))
复制代码

至此,一个最简单的WebRTC链接已经创建完成。

3. 数据通道

WebRTC擅长进行数据传输,不只仅是音频和视频流,还包括咱们但愿的任何数据类型,相比于复杂的数据交换过程,建立一个数据通道这个主要功能已经在RTCDataConnection对象中实现了:

var peerConnection = new RTCPeerConnection();
var dataChannel = peerConnection.createDataChannel("label",dataChannelOptions);
复制代码

WebRTC会处理好全部的事情,包括浏览器内部层。浏览器经过一系列的事件来通知应用程序,当前数据通道所处的状态。ondatachannel事件会通知RTCPeerConnection对象,RTCDataChannel对象自己在开启、关闭、发生错误或者接收到消息时会触发对应的事件。

dataChannel.onerror = function (error){
    console.log(error)
}

dataChannel.onmessage = function (event){
    console.log(event.data)
}

dataChannel.onopen = function (error){
    console.log('data channel opened')
    // 当建立一个数据通道后,你必须等onopen事件触发后才能发送消息
    dataChannel.send('Hello world')
}

dataChannel.onclose = function (error){
    console.log('data channel closed')
}
复制代码

数据通道datachannel创建的过程略微不一样于创建视频流或音频流双向链接,offer、answer、ice处理完毕以后,由一方发起请求便可。

localConnection = new RTCPeerConnection();

sendChannel = localConnection.createDataChannel("sendChannel");
sendChannel.onopen = handleSendChannelStatusChange;
sendChannel.onclose = handleSendChannelStatusChange;
复制代码

接收方此时并不须要再次调用createDataChannel方法,只须要监听RTCPeerConnection实例对象上的ondatachannel事件就能够在回调中拿到发送方的请求,数据通道就创建起来了。

remoteConnection = new RTCPeerConnection();
remoteConnection.ondatachannel = receiveChannelCallback;

function receiveChannelCallback(event) {
    receiveChannel = event.channel;
    receiveChannel.onmessage = handleReceiveMessage;
    receiveChannel.onopen = handleReceiveChannelStatusChange;
    receiveChannel.onclose = handleReceiveChannelStatusChange;
  }
复制代码

dataChannelOptions传入的配置项是可选的,而且是一个普通的JavaScript对象,这些配置项可使应用在UDP或者TCP的优点之间进行变化。

  • reliable:设置消息是否进行担保
  • ordered:设置消息的接受是否须要按照发送时的顺序
  • maxRetransmitTime:设置消息发送失败时,多久从新发送
  • maxRetransmits:设置消息发送失败时,最多重发次数
  • protocol:设置强制使用其余子协议,但当用户代理不支持该协议时会报错
  • negotiated:设置开发人员是否有责任在两边建立数据通道,仍是浏览器自动完成这个步骤
  • id:设置通道的惟一标识

4. 文件共享

目前,数据通道支持以下类型:

  • String:JavaScript基本的字符串
  • Blob(binary large object):二进制大对象
  • ArrayBuffer:肯定数组长度的数据类型
  • ArrayBufferView:基础的数组视图

其中,Blob类型是一个能够存储二进制文件的容器,结合HTML5相关文件读取API,能够实现文件共享的功能。

5.更多

MDN文档:>>>点我进入

WebRTC学习资料大全:>>>点我进入

官方Github地址:>>>点我进入

SDP字段解析:>>>点我进入

我的demo代码地址:>>>点我进入

书籍《WebRTC权威指南》,《Learning WebRTC 中文版》

相关文章
相关标签/搜索