WebRTC专栏:基本知识储备

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

在认识Web RTC之前,需要先链接几个重要的框架:

ICE(Interactive Connectivity Establishment)
ICE诞生的原因:由于Peer对Peer直连的方式受多重因素的限制,比如防火墙,公共IP,路由等。因此需要一个灵活的框架去除这些因素的影响,允许web浏览器与Peer节点连接的框架。而这个框架统称为ICE,ICE的背后使用的是STUN和TURN服务。
STUN(Session Traversal Utilities for NAT)
STUN主要解决两个问题:查询自己的公共IP和定位阻止Peer创建连接失败的原因。
PeerA要和PeerB通信,流程大致如下:

PeerA -> STUN : 我的公网IP是啥?
STUN -> PeerA: 你的公网IP是 208.121.55.130:3255

PeerB -> STUN : 我的公网IP是啥?
STUN -> PeerB: 你的公网IP是 208.131.59.131:3253

通过询问STUN后Peers就知道自己公网通信地址,就可以顺利的和其他Peer创建连接了。

NAT (Network Address Translation)
NAT的出现,本质上是为了解决IPV4地址不够用的问题,地球上的设备如此之多,设备之间要通信必须是公共IP, 但是公共的IP地址有限,因此NAT将通过 私有IP段+端口 的方式唯一定位一台设备,这样就顺利的解决私有网段上设备通信的问题。
但是,仅解决这些问题还不够!因为有些路由器对NAT的访问再做一层Symmetric NAT限制,同样会导致创建连接失败,因此为了解决这个问题,又引入了TURN.

TRUN(Traversal Using Relays around NAT)
使用TURN遍历意味着通过打开一个与TURN服务器的连接并通过该服务器转发所有信息来绕过Symmetric NAT限制。PeerA创建一个与TURN服务器的连接,并告诉其他的Peer发送数据包到服务器,然后TURN再将转发给请PeerA。这显然会带来一些开销,所以只有在万不得已的情况下才使用它。
SDP(Session Description Protocol)
SDP是一种描述连接的多媒体内容的标准,如分辨率、格式、编解码器、加密等,以便数据传输时双方能够相互理解。本质上,这是描述内容的元数据,而不是媒体内容本身。因此,从技术上讲,SDP不是真正的协议,而是用于描述设备之间共享媒体的连接的数据格式。

Signaling server

在webrtc中,信令服务器起着重要的作用,信号服务器的工作是充当中介,让两个对等点查找和建立连接,同时尽可能减少潜在的私有信息的暴露。webrtc可以使用WebSocket或者XMLHttpRequest进行peers之间的通信。

1. 建立了交换消息的机制

chat server在client和server使用WebSocket API发送json格式的数据,通过指定不同的消息类型来处理不同的任务,比如注册新用户,设置用户名,发送广播消息等。在源码的chatserver.js中对此操作进行了封装。

1.找到接受方,并调用sent方法发送消息,其中connectionArray的元素是WebSicjet对象。

function sendToOneUser(target, msgString) {
  var isUnique = true;
  var i;

  for (i=0; i<connectionArray.length; i++) {
    if (connectionArray[i].username === target) {
      connectionArray[i].send(msgString);
      break;
    }
  }
}
  1. 如果没有指定接收方,则对所有人进行消息的发送。
if (sendToClients) {
  var msgString = JSON.stringify(msg);
  var i;

  if (msg.target && msg.target !== undefined && msg.target.length !== 0) {
    sendToOneUser(msg.target, msgString);
  } else {
    for (i=0; i<connectionArray.length; i++) {
      connectionArray[i].send(msgString);
    }
  }
}

2. 定义消息的格式

也就是定义发送端和接收端如何发送和处理接受消息。消息的格式如下:

type: video-offer | video-answer
name: 发送方的名字
target: 接收方的名字
sdp: 发送方的sdp

首先,caller和callee之间需要互换session descriptions, caller会发送type='video-offer'的消息给callee,callee会发送type='video-answer'的格式给caller。在这个过程中,双方协商了之后使用寿命codec进行media的通信,但是并未开始media的传输,media的传输是在ICE上完成的。

3. 互换ICE candidates

Peer之间需要互相发送ICE candidates来协商确定自己是否在对方的candidates列表里,即使meida流已经在传输,他们直接依然可能还在互换candidates信息。
icecandidate事件被发送到RTCPeerConnection,然后使用pc.setLocalDescription(offer)完成添加SDP。
一旦两个Peers之间发现互相匹配了之后,他两就会通过SDP来建立连接,然后开始media的传输,如果有新的更高质量的candidates请求进来,那么已经开始传输的media也会根据需要改变格式。

互换ICE candidates是消息格式为:

type: new-ice-candidate
target: 接收方的名字
sdp: candidate的sdp

4. 消息传输流程

信令传输的过程涉及到信令服务器在两个对等点之间交换消息。当然,确切的过程会有所不同,但一般来说,处理信号信息的几个关键点是:

  • 每个用户的web浏览器
  • 信令服务器
  • 托管聊天服务的web服务器
    加入Naomi和Priya需要使用视频会议,那么其事件的流程如下:
screencapture-media-prod-mdn-mozit-cloud-attachments-2016-01-27-12363-9d667775214ae0422fae606050f60c1e-WebRTC-Signaling-Diagram-svg-2020-07-17-11_12_05.png

当每个Peer的ICE层开始发送candidates时,它将进入链中各个点之间的交换,如下所示:

screencapture-media-prod-mdn-mozit-cloud-attachments-2016-01-27-12365-b5bcd9ecac08ae0bc89b6a3e08cfe93c-WebRTC-ICE-Candidate-Exchange-svg-2020-07-17-13_07_52.png

下面将通过一个小的demo展示WebRTC是如何通过WebSocket实现聊天的。
demo的效果请访问:https://webrtc-from-chat.glitch.me/
demo的源码: https://github.com/mdn/samples-server/tree/master/s/webrtc-from-chat

会话描述(Session decription)

WebRTC连接上端点的配置称为会话描述。该描述包括有关正在发送的媒体类型,其格式,使用的传输协议,端点的IP地址和端口的信息,以及描述媒体传输端点所需的其他信息。
当用户向另一个用户发起WebRTC呼叫时,会创建一个特殊的描述,称为offer。此描述包括有关呼叫者为呼叫建议的配置的所有信息。然后,接收者用一个answer来回应。以此方式,两个设备彼此共享为了交换媒体数据所需的信息。这种交换是使用ICE处理的,该协议允许两个设备使用中介程序交换要约和答复,即使两个设备之间都被网络地址转换(NAT)隔开。

然后,每个Peer都保留两个描述:本地描述(描述自己)和远程描述(描述呼叫的另一端)。

offer/answer过程不仅在首次建立呼叫时执行,而且在呼叫格式或其他配置需要更改时都执行。不管是新呼叫还是重新配置现有呼叫,以下这些offer/answer都是必须执行的基本步骤(ICE逻辑除外):

  • 呼叫者通过捕获本地媒体 navigator.mediaDevices.getUserMedia()
  • 呼叫者创建 RTCPeerConnection 并调用 RTCPeerConnection.addTrack()
  • 呼叫者调用用 RTCPeerConnection.createOffer() 以创建offer。
  • 呼叫者调用 RTCPeerConnection.setLocalDescription() 以将该offer设置为本地描述(即连接本地端的描述)。
  • setLocalDescription() 之后,呼叫方要求STUN服务器生成ICE candidates
  • 呼叫者使用信令服务器将offer发送到呼叫的预期接收者。
  • 接收者收到offer,并调用 RTCPeerConnection.setRemoteDescription() 将其记录为远程描述(连接另一端的描述)。
  • 接收者会在通话结束时进行所有必要的设置:捕获其本地媒体流,然后通过 RTCPeerConnection.addTrack()将媒体流对接到连接上。
  • 然后,接收者通过调用 RTCPeerConnection.createAnswer()来创建answer。
  • 接收者调用 RTCPeerConnection.setLocalDescription(),并传入创建answer,以将answer设置为其本地描述。至此,接受者已经知晓connection两端的配置。
  • 接收者使用信令服务器将answer发送给呼叫者。
  • 呼叫者收到answer。
  • 呼叫者调用 RTCPeerConnection.setRemoteDescription() 以将answer案设置为呼叫结束的远程描述。现在,呼叫者也同步了两端的配置化信息。流媒体就可以开始按配置传输了。
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342