前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WebP2P 让你的直播免流

WebP2P 让你的直播免流

作者头像
villainhr
发布2018-07-03 15:07:31
1.9K0
发布2018-07-03 15:07:31
举报
文章被收录于专栏:前端小吉米前端小吉米

你在下载的时候,有没有体验过 P2P 下载,能够让你的网速从 10KB 直接提升到 10MB? 你在企业内传输文件的时候,有没有体验过文件秒传? 你在看直播的时候,想不想用别人的流量看直播呢? ...

能做到上面这些场景的技术,叫做 P2P。P2P 技术中,最出名的叫做 WebRTC。WebRTC 是一个含金量非常高的技术。做好的话你可以养活一家公司,做不好,那就只能是一个 demo。

WebRTC 虽然能做很多事,但是并不是所有场景都适合。最大的使用场景是 两个终端在同一个 NAT 内,简单来说,都在一个 wifi 内。这个场景中,最显著的效果就是带宽无限并且高速,你走的就是内部的线路,根本不消耗运营商的流量。

P2P 技术在基于 WebRTC 标准下,可以做很多事情:

  • 录屏应用
  • APP Drop
  • 视频直播
  • ...

作为 Web 开发,WebRTC 又能够给前端赋能些什么呢?

在了解这些基本内容后,接下来,我们会从底层一步一步介绍一下 P2P 在 Web 直播的应用。

P2P 穿透

P2P 穿透也可以叫做 NAT 穿透,这是 P2P 最大的一个难点。为了解决 ipv4 不够用,推出了 NAT 技术。NAT (Network Address Translation)是用来将内网私有 ip,转化为公有 ip。简单点,就是让很多台电脑公用同一个 IP。但是 NAT 有个非常重要的点:

NAT 不允许外网主机主动访问内网主机。

这个不允许访问的机制也有很多种,根据这些特性,我们可以将 NAT 分为多种:

  • 完整锥型NAT(Full Cone NAT)
  • 受限锥型NAT(Restricted Cone NAT):
  • 端口受限型NAT(Port Restricted Cone NAT)
  • 对称型NAT(Symmetric NAT)

一般情况下,前面三种 NAT 是可以穿透的,但是,对称型NAT 无法穿透。具体内容,大家网上搜一搜 NAT 穿透,资源应该很多。在穿透时,我们不仅需要考虑 NAT 还需要考虑到集群机器的防火墙设定,如果防火墙限制了 UDP 打洞,那么我们还需要切换为 TCP 打洞(TCP 打洞一般会慢一点)。

总的来说,我们穿透时需要考虑的问题就有:

  • NAT 类型
  • 两端处在 NAT 的位置:都在一层 NAT 后还是多层 NAT 后...
  • 防火墙连接协议的设定

这些问题一旦组合起来,这个复杂度就是 N*N 的关系了。如果搭建 p2p 每次都需要从头解决这个内容,P2P 也不会像现在发展的这么好了。WebRTC 就是用来解决这一问题的标准模板,通过 STUN/TURN Server 来实现打洞穿透。

WebRTC 打洞流程

这里,我们按照一个比较常见的情况作为模板讲解一下。两端都位于 NAT 层背后,并且,NAT 是可以穿透的 Full Cone NAT 类型。具体穿透流程如下:

  • A 和 B 需要和 STUN 服务器建立连接,获得 A/B 的公网 ip:port 和私网 ip:port。
  • B 往 A 发送一个打洞包,此时,已经在 B 的 NAT 上留下到 A 的 打洞 session。但是,由于该包没有 A NAT 的 session 记录,会被 A 拒绝掉。
  • A 往 B 发送一个打洞包,该包会在 A 的 NAT 上增加 B 的 session。此时,由于 B 的 NAT 上存在 A 的 session,该包是可以直接被 B 的 NAT 通过的。
  • 打洞完成

在 WebRTC 完成这里流程的 API 是: RTCPeerConnection。通过自建的一个中间 Server,来交换指定的 SDP 和 candidate。

SDP 是当前 Point 的一些基本描述信息,当前 WebRTC 版本 ICE 的描述信息,以及,对已经连接的 ICE 内容的描述,比如 video/audio 信息。SDP 这一环节,其实就是告诉了哪两个 Point 会进行连接。本身和打洞并没有太大的关联。具体内容可以参考:SDP antonomy

candidate 则是打洞的关键信息,里面会包含当前 Point 的内外网 ip:port,以及防火墙设定规则 tcp/upd。这里有一点需要注意的是,一个 point 为了能够提高 NAT 打洞的成功率,会产生多个 candidate。这里主要取决于几个 candidate 里面几个基本参数:

  • sdpMid 用来指定该次 candidate 的传输的 mediaStream 内容。例如, videoaudio
  • protocol:指定连接的协议, tcpudp
  • type: 表示能够穿透 NAT 的类型
    • host: 能够直连,或者在同一个 NAT 内
    • srflx/prflx: 外网直连通道,STUN 已经帮忙打了一个洞。如果两端不在同一个 NAT 里面,会用到该内容.
    • relay:是 TURN 服务器的中转通道。针对的是,对称型的 NAT,数据交换只能走中间的 server。

不过, srflx/prflx 类型的 candidate 只会在你初始化 RTCPeerConnection时,传入 iceServers 的 STUN 服务器 URL 时,才会获得。

代码语言:javascript
复制
config = {
     "iceServers": [{
         "urls": ["stun:stun.l.google.com:19302"]
     }],
     "iceTransportPolicy": "all",
     "iceCandidatePoolSize": "0"
 }

在 webRTC 代码层面,我们并不需要额外针对 candidate 做逻辑处理。我们只需要将 candidate 传给另外一端,通过 addIceCandidate() 注册到 RTC 内部即可。

代码语言:javascript
复制
local.addIceCandidate(remoteCandidate)
.then(e=>{
    console.log("add success");
})

通过云服务器完成 candidate 和 sdp 信息的交换后,我们就已经做完了 RTC 连接的必要准备。剩下的就是在连接建立完成之后做的状态监听和其他扩展事情。

连接状态判断

这里面最大的一个问题在于,我们完成数据添加之后,怎么判断 P2P 是否连接上。WebRTC 提供了我们 7 个基本的事件监听:

代码语言:javascript
复制
attribute EventHandler  onnegotiationneeded;
attribute EventHandler  onicecandidate;
attribute EventHandler  onicecandidateerror;
attribute EventHandler  onsignalingstatechange;
attribute EventHandler  oniceconnectionstatechange;
attribute EventHandler  onicegatheringstatechange;
attribute EventHandler  onconnectionstatechange;

通过 onconnectionstatechange 就可以得到连接状态的变化。直接绑定该方法,即可获得相关内容:

代码语言:javascript
复制
peer.addEventListener('connectionstatechange',event=>{
    // get the state from event
},false);

其能够提供的事件回调信息,可以直接参考:connection states。里面,我们只需要判断状态是否是 connected,来决定该次连接是否成功。

如果不成功,我们可以直接从 onicecandidateerror 里面获得相关的错误信息,具体可以参考:ICE gather error。当然,在连接过程中,也可以直接从 Promise 中,获得连接失败的信息,这部分内容可以直接参考:RTC Error。

上面整个代码流程可以直接参考:webRTC trickle candidate

DataChannel 数据穿洞

打洞过程是 WebRTC 最基础的一步,如果连这一步都没成功,那么后面就需要做一些其它适配的兼容。比如,直接通过 CDN 拉去资源。WebRTC 打洞成功后,我们就可以利用这个打洞包,根据用户的种子资源数、上行带宽、下载进度来判断 P2P 传输的资源。

WebRTC 原生提供了 RTC Media API、RTCDataChannel、DTMF 这三个传输通道。Media 能够直接结合 getUserMedia API 传输当前摄像头和麦克获取的音视频。并且 Chrome 浏览器在底层内嵌了很多功能强大的编码器,这里可以直接参考:webRTC FRQ.

不过,经过测试 WebRTC 回声消除和双端同时对话的效果并不是特别好。这块,大家可以考虑一下,能不能直接在底层替换编码器或者购买其他服务。

Media 和 DTMF 通常都需要建立在 getUserMedia 的前提下,但是,IOS11 并不支持,它只支持 DataChannel 传输数据的 API。所以,这里,我们只会针对 DataChannel 来做一些讲解。如何通过 DataChannel 来传输你的自定义文件内容。

DataChannel 是 PeerConnection 的一个拓展 API,可以直接通过 createDataChannel 来创建一个 SCTP 通道。SCTP 是一种高效的帧传输协议,它和 TCP/UDP 是在同一层的,集中了两者之间的优势。我们只需要在发送端创建 Channel,接收端直接监听 ondatachannel 事件即可。

代码语言:javascript
复制
let senderChannel = localPeer.createDataChannel('dataChannel');
senderChannel.onopen = ()=>{
    if(senderChannel.readyState === 'open'){
        senderChannel.send(someBuffer);
    }

};

senderChannel.birnayType = 'arrayBuffer';

remotePeer.ondatachannel = function(event){
    // receive data from event.channel
    remotePeer = event.channel;
    remotePeer.binaryType = 'arraybuffer';
    remotePeer.onmessage = onReceiveMessageCallback;
}

RTCDataChannel 一共可以发送两种数据:String 和 Binary(也可以叫做 ArrayBuffer,ArrayBufferView or Blob) 具体直接参考:dataView。

Channel 具体的用法其实就和 WebSocket 一样,通过 send 来传递相关的信息,再监听 onmessage 事件获得数据的回调。

上面的流程大致的覆盖了打洞的云端流程,比如穿透 NAT 层,P2P 数据 Channel 建立。不过,中间还有很多细节并没有解决清楚:

  • 怎么找到最优的 Point
  • 需要传输的数据是哪些
  • 传输数据的进度控制

而这些问题就需要落地到具体的业务当中了。因为现在直播行业非常的火热,本人也在该行业里面摸爬滚打,了解到该行业一些基本的痛点。最大的就是非常吃带宽,为了解决这一问题,我们完全可以利用 P2P 来做直播带宽的节省。

但是,说起来很容易,怎么做这才是关键?

不过,对于 Web 开发来说,这里只介绍一下 的基本思路。在 Web 直播中比较流行的是通过 http-chunked 模式来实现直播。而 http-chunked 协议很难得到具体播放的进度,那我们就需要一个能够很容易获得播放进度的协议--切片协议。

对于切片协议而言,最为突出的就是 HLS,但是它的延时性过高,没办法满足直播低延时的问题。针对这个点,MPEG 提出了一个 DASH 协议,来作为直播内容协议的补充。直播 DASH 是基于 HTTP-URL 的动态直播协议,通过 URL 上面的时间戳就很容易做到对流的时间记录,整个端的 P2P 流程图为:

云端这一步,就主要在 SegmentProtocol 做的事情,右边的则是本地播放的 IS/MS 处理。而如果你能够在云上做好这一整套流程,比如:

  • 确定最佳上行 Peer
  • 维护一整套种子和资源的云端管理
  • Peer 纠错机制
  • WebRTC 和 DASH 的最佳切换

那么,你的 P2P 功能和编码能力应该比一般程序员高太多了。

入门 Tip

事情需要一点一点做,饭需要一口一口的吃,DASH 由于协议比较复杂,推荐大家先从 HTTP-Chunked 协议入手,自己先搭建一个直播的 DEMO 试试水,这里推荐一下 HTTPLIVE 库。

另外,如果读者对前端音视频很感兴趣,不甘心只做一个纯纯的 UI 工程师的话,可以直接关注我的公众号前端小吉米,输入 MSE 加入 前端音视频的交流小组

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-02-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端小吉米 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • P2P 穿透
  • WebRTC 打洞流程
    • 连接状态判断
    • DataChannel 数据穿洞
    相关产品与服务
    云直播
    云直播(Cloud Streaming Services,CSS)为您提供极速、稳定、专业的云端直播处理服务,根据业务的不同直播场景需求,云直播提供了标准直播、快直播、云导播台三种服务,分别针对大规模实时观看、超低延时直播、便捷云端导播的场景,配合腾讯云视立方·直播 SDK,为您提供一站式的音视频直播解决方案。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档