WebRTC 中的 ICE 实现

WebRTC 中的 ICE 实现

  • WebRTC 中的 ICE 实现
    • Candidate 种类与优先级
    • ICE 策略
    • P2P 连接
      • 完全锥型 NAT
      • IP 限制锥型 NAT
      • 端口限制锥型 NAT
      • 对称型 NAT
      • NAT 类型检测
      • 如何进行 NAT 穿越
    • 网络中继
      • TURN 协议中转数据
      • WebRTC 使用 TURN 协议
      • STUN/TURN 服务器的安装与部署

WebRTC 中的 ICE 实现

Candidate 种类与优先级

ICE中使用的Candidate具有优先级次序,由高到低分别为host、srflx、prflx、relay。WebRTC进行一对一音视频通信时,就是按照这个次序尝试建立连接的。

WebRTC通信时会按照内网、P2P、relay这样的次序尝试连接:

  1. 内网连接对应host连接策略。host连接表示直接在本地设备上建立的连接,也就是在同一局域网内的设备之间的直接连接。
  2. 不在同一局域网内,双方尝试host型Candidate连接时会失败。不过,在双方尝试连接时,双方Candidate的收集工作并未停止。Candidate收集线程还在收集其他类型的Candidate,如从STUN/TURN服务器收集srflx和relay类型的Candidate。
  3. P2P连接对应srflx和prflx连接策略。srflx(server reflexive)和prflx(peer reflexive)连接都是通过STUN服务器获取的公共IP地址,用于建立点对点连接。srflx连接是通过NAT后的公共IP地址建立的连接(当收集到srflx类型的Candidate时,ICE会尝试NAT打洞),而prflx连接是对等方自己的NAT映射地址。
  4. 中继连接对应relay连接策略。当无法建立直接的P2P连接时,WebRTC会使用TURN服务器作为中继,建立relay连接。relay连接通过中继服务器传递数据,确保数据的可靠传输。

请添加图片描述

总结:

  • WebRTC的ICE机制会选择最好的链路传输音视频数据,即如果通信的双方在同一网段内,则优先使用内网链路;如果通信的双方不在同一网段,则优先使用P2P;当以上方式都无法连通时,则使用relay服务进行中转。
  • ICE的连通率几乎可以达到100%。在内网和P2P无法连通的情况下,它还可以通用中继的方式让彼此连通,从而大大提高了WebRTC的连通率。

WebRTC中的ICE既考虑了数据传输的效率,又考虑了网络的连通率,实现起来也简单。

ICE 策略

RTCPeerConnection提供了一种在浏览器之间建立点对点连接的方式,而无需通过服务器进行中转。它使用了ICE(Interactive Connectivity Establishment,交互式连接创建)协议来处理网络地址和端口的自动配置,以确保连接的稳定性和可靠性。

构造RTCPeerConnection对象时,其输入参数的类型为RTCConfiguration。参数 configuration 是一个 JSON 对象,用于提供配置新连接的选项。

在这里插入图片描述

下面是 RTCConfiguration 各字段的含义:

在这里插入图片描述

iceServers是RTCIceServer类型的数组,可以包含一个或多个STUN和/或TURN服务器。

dictionary RTCIceServer {required (DOMString or sequence<DOMString>) urls;DOMString username;DOMString credential;RTCIceCredentialType credentialType = "password";
};

各字段含义:

  1. url:服务器地址;
  2. username:访问该服务器时使用的用户名;
  3. credential:访问该服务器时使用的密码;
  4. credentialType:指明授权方式为密码方式,也是目前唯一的授权方式。

更详细的介绍:WebRTC 的核心:RTCPeerConnection

RTCConfiguration 实例:

RTCConfiguration pcConfig = {'iceServers': [{'urls': 'turn:stun.learningrtc.cn:3478','username': "username1",'credential': "password1",},{'urls': 'turn:stun.avdancedu.com:3478','username': "username2",'credential': "password2",}],'iceTransportPolicy': "all",'bundlePolicy': "max-bundle",'rtcpMuxPolicy': "require"
};
RTCPeerConnection pc = new RTCPeerConnection(pcConfig);

解释:

  1. iceServers 包含两个 TURN 服务器,相当于为 WebRTC 增加了两个 relay 类型的 Candidate。当内网和P2P无法连通时,RTCPeerConnection 会尝试与这两台中继服务器连接。如果其中一台连接成功,就不会尝试另一台。
  2. iceTransportPolicy 为 “all”,表示所有的 ICE 候选都会被考虑,按 Candidate 的优先级次序尝试连接。
  3. bundlePolicy 为 “max-bundle”,所有媒体数据使用同一个 Candidate,这样更有利于端口资源的利用。
  4. rtcpMuxPolicy 为 “require”,表示 RTCP 和 RTP 数据共用一个 Candidate。

P2P 连接

这里的 P2P 指的就是如何进行 NAT 穿越。NAT在真实的网络环境中随处可见,它的出现主要出于两个目的:

  1. 为了解决IPv4地址不够用的问题。当时IPv6短期内还无法替换IPv4,而IPv4的地址又特别紧缺,所以人们想到让多台主机共用一个公网IP地址,大大减缓了IPv4地址不够用的问题。
  2. 为了解决安全问题。使用NAT后,主机隐藏在内网,这样黑客就很难访问到内网主机,从而达到保护内网主机的目的。

请添加图片描述

NAT就是一种地址映射技术,它在内网地址与外网地址之间建立了映射关系。当内网主机向外网主机发送信息时,数据在经过NAT层时,NAT会将数据包头中的源IP地址和源端口号替换为映射后的外网IP地址和外网端口。相反,当接收数据时,NAT收到数据后会将目标地址映射为内网的IP地址和端口再转给内网主机。

请添加图片描述

RFC3489和RFC5389是最重要的两份NAT穿越的协议文档。在RFC3489协议中,将NAT分成4种类型,即完全锥型、IP限制锥型、端口限制锥型以及对称型。在这4种类型中,越往后的NAT类型穿越难度越大。

大多数情况下NAT穿越使用的是UDP,这是因为UDP是无连接协议的,打洞会更加方便。当然,也可以使用TCP打洞。

完全锥型 NAT

完全锥型NAT的特点:一旦打洞成功,所有知道该洞的主机都可以通过它与内网主机进行通信。

当 host 主机通过 NAT 访问外网主机 B 时,就会在 NAT 上打洞。如果主机 B 将该洞的信息分享给主机 A 和 C,那么它们也可以通过该洞给内网的 host 主机发送消息。

在这里插入图片描述

“洞”就是 NAT 上的一个内外网的映射表,其格式为:{内网IP,内网端口号,外网IP,外网端口号}。有了这个映射表,所有发向洞的数据都会被 NAT 中转到内网的 host 主机。在 host 主机上,所有侦听其内网端口的应用程序可以收到所有发向它的数据。

IP 限制锥型 NAT

IP限制锥型NAT要比完全锥型NAT严格得多。IP限制锥型NAT的主要特点:NAT打洞成功后,只有与之打洞成功的外网主机才能通过该洞与内网主机通信,而其他外网主机即使知道洞口也不能与之通信。

在这里插入图片描述

只有 host 主机访问过的外网主机才能穿越这个洞。

IP 限制锥型 NAT 的映射表是一个五元组,其格式为:{内网IP,内网端口号,外网IP,外网端口号,[被访问主机的IP,…]}。当外网主机通过 IP 限制锥型 NAT 向内网主机发送消息时,NAT 会检测数据包头的源 IP 地址是否在 NAT 映射表中有记录。如果有,说明是合法数据,可以进行数据转发;如果没有记录,说明非法,NAT 将该数据包直接丢弃。

端口限制锥型 NAT

端口限制锥型NAT的主要特点:除了像IP限制锥型NAT一样需要对IP地址进行检测外,还需要对端口进行检测。

在这里插入图片描述

端口限制锥型 NAT 的映射表是一个五元组,其格式为:{内网IP,内网端口号,外网IP,外网端口号,[{被访问主机的IP,被访问主机的端口},…]}。

对称型 NAT

对称型NAT是4种NAT类型中对数据包检测最严格的。对称型NAT的特点:内网主机每次访问不同的外网主机时,都会生成一个新洞,而不像前面3种NAT类型使用的是同一个洞。

请添加图片描述

对称型NAT的映射表是一个六元组,其格式为:{内网IP,内网端口号,外网IP,外网端口号,被访问主机的IP,被访问主机的端口}。

对称型NAT每次访问不同外网主机都生成新洞的这种特性,导致对称型NAT碰到对称型NAT或者对称型NAT遇到端口限制型NAT时,双方打洞的成功率非常低,即使可以互通,成本也非常高。WebRTC遇到上面这两种情况时,直接放弃打洞的尝试。

NAT 类型检测

RFC3489 协议中给出了标准的 NAT 类型检测流程:

请添加图片描述

内网主机进行 NAT 类型检测时,需要两台 STUN 服务器,每台 STUN 服务器又需要两块网卡,每块网卡需要配置公网 IP 地址。

检测过程:

  1. 检测是否在NAT之后或者UDP socket是否阻塞
    向IP1:PORT1发送数据包,要求IP1:PORT1返回数据包源地址和端口号,同时设置socket timeout,重复一定次数后,如果一直未收到数据包回复,表明UDP通信被阻塞。如果收到数据包,和自身的IP:port对比,如果相同,则表明没有经过NAT,不同则表明一个是外网IP,一个是内网IP,且经过NAT设备。

  2. 检测是否为完全锥形NAT
    向IP1:port1发送数据包,要求IP2:port2向目的主机发送数据包,如果目的主机可以接收,表明是完全锥形NAT.

  3. 检测是否为对称形NAT
    向IP2:port2发送数据包,要求返回数据包的外网地址和端口号,将其与步骤2的外网地址和端口号对比,如果完全相同,则为限制锥形NAT或者端口限制NAT,否则为对称形NAT。

  4. 检测是否为限制锥形NAT或者端口限制NAT
    向IP2:port2发送数据包,由IP2:port3向源地址返回数据,如果可以收到,表明为限制锥形,否则为端口和IP限制锥形。

如何进行 NAT 穿越

各 NAT 之间可穿越表:

NAT 类型NAT 类型能否穿越
完全锥型 NAT完全锥型 NAT可以
完全锥型 NATIP 限制锥型 NAT可以
完全锥型 NAT端口限制锥型 NAT可以
完全锥型 NAT对称型 NAT可以
IP 限制锥型 NATIP 限制锥型 NAT可以
IP 限制锥型 NAT端口限制锥型 NAT可以
IP 限制锥型 NAT对称型 NAT可以
端口限制锥型 NAT端口限制锥型 NAT可以
端口限制锥型 NAT对称型 NAT不可以
对称型 NAT对称型 NAT不可以

可以看出,完全锥型 NAT 和 IP 限制锥型 NAT 可以与其他任何类型的 NAT 互通。而最后两种情况因为互通成本太高,不必尝试 NAT 穿越。

网络中继

当遇到NAT之间无法打通的情况时,WebRTC会使用TURN协议通过中转的方式实现端与端之间的通信。

TURN 协议中转数据

TURN协议采用了典型的客户端/服务器模式,其服务器端称为TurnServer,客户端称为TurnClient。TurnClient与TurnServer之间通过信令控制数据流的发送。

TURN协议底层依赖于STUN协议。值得一提的是,TURN协议本身是STUN协议的一个拓展,因此绝大部分TURN报文都是STUN类型的,作为STUN的一个拓展,TURN增加了新的方法(method)和属性(attribute)。

下图就是一个 TURN 服务中转的实例,有个TURN client端和一个TURN Server端以及两个Peer对端。

在这里插入图片描述

在上图中,左边的 TurnClient 是位于 NAT 后面的一个客户端(内网地址是10.1.1.2:49721)。TurnClient 首先向 TurnServer 的 3478 端口发送 Allocate 指令。TurnServer 收到该消息后,在 TurnServer 分配一个与 TurnClient 对应的 Relay 地址(192.0.2.15:50000),任何发向 Relay 地址的数据都会被转发到 TurnClient 端。

主机 A 和 B 不是 TurnClient,它们被称为 Peer 端。Peer 端可以使用 UDP 向 TurnServer 的 Relay 地址发送数据,TurnServer 根据映射关系,将 Relay 地址收到的数据转给对应的 TurnClient。

注意,TurnClient 和 TurnServer 之间的传输协议可以是 UDP 或者 TCP。而在 TurnServer 上分配的 Relay 地址使用的都是 UDP。

TurnServer 上的每一个 allocation 都唯一对应一个 TurnClient,并且只有一个中继地址,因此当数据包到达某个中继地址时,服务器总是知道应该将其转发到什么地方。
但值得一提的是,一个 TurnClient 可能在同一时间在一个 TurnServer 上会有多个 allocation,这和上述规则是并不矛盾的。

TURN 协议对应端到端传输数据提供了 2 种方法:

  1. Send/Data indication:指令 Send indication(XOR-PEER-ADDRESS、DATA) 用于 TurnClient 向某个 Peer 端发数据,其中 XOR-PEER-ADDRESS 属性用于指定向哪个主机转发数据,DATA 属性指明数据的具体内容。相反,当 Peer 端通过 TurnServer 向 TurnClient 发数据时,使用 Data indication 指令,指明向哪个 TurnClient 转发数据。
  2. tunnel机制:使用tunnel机制的好处是不用再像使用Send/Data indication指令一样,每次都要指定数据发往的地址,只需要在开始发送数据之前,发送ChannelBind指令将channel number与目标地址绑定一次即可,后面统一使用channel number就可以找到发往的目的地。

WebRTC 使用 TURN 协议

WebRTC 收集到的 relay 类型 Candidate,指的就是通过 TURN 协议的 Allocation 指令分配的地址。

WebRTC通信的两端既是 TurnClient,因此都可以使用 TURN 协议与 TurnServer 建立联系;又是彼此的 Peer 端,因此可以向对端的 Relay 地址发送数据,从而让 TurnServer 将数据中转给对端。

在这里插入图片描述

3478 是一个多路复用的端口:

  1. 接收 Allocate 指令:TurnClient 首先向 TurnServer 的 3478 端口发送 Allocate 指令。TurnServer 收到该消息后,在 TurnServer 分配一个与 TurnClient 对应的 Relay 地址。
  2. TurnServer 从 Relay 地址收到数据后,将其打包成 TURN 消息,也要经过 3478 端口转发给对应 TurnClient。

STUN/TURN 服务器的安装与部署

公网上的 STUN/TURN 服务器的安装与部署一般采用云主机。目前比较流行的是 Google 开源的 coturn 服务器。

基本步骤:

  1. 获取 coturn 源码:https://github.com/coturn/coturn。
  2. 编译安装。
  3. 配置 coturn:配置一下侦听的端口(默认为 3478)、指定云主机的公网 IP 地址、访问 STUN/TURN 服务的用户名和密码。
  4. 启动 STUN/TURN 服务。
  5. 测试 STUN/TURN 服务:打开trickle-ice 测试工具,按要求输入 STUN/TURN 地址、用户名和密码就可以探测 STUN/TURN 服务运行是否正常。

STUN/TURN 部署好后,就可以使用它转发多媒体数据,不用担心通信双方因 NAT 或防火墙等原因而无法通信的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/10723.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库原理及应用--事务

事务是一组操作的集合&#xff0c;是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求&#xff0c;即这些操作要么同时成功&#xff0c;要么同时失败。 比较经典的事务:银行转账业务。 张三向李四转1000&#xff0c;这个时候&am…

如何衡量和提高客户满意度?

客户满意度衡量客户对你的产品或服务的喜爱程度。在某些情况下&#xff0c;它可以成就或毁掉企业业务。高度满意的客户更有可能保持忠诚并在未来花费更多。另一方面&#xff0c;不满意的客户更有可能转向竞争对手的品牌。 那么&#xff0c;如何保持较高的客户满意度呢&#xf…

如何打破数据管理僵局,释放数据资产价值?[AMT企源案例]

引言 数据是企业信息运作的核心和基础&#xff0c;是影响企业决策的关键要素&#xff0c;而主数据是数据中的最基础和公共的部分。面临长期以来的数据治理缺失导致的杂论局面&#xff0c;如何有条不紊推进主数据管理&#xff0c;让数据资产“活”起来&#xff1f;S集团的做法非…

torch_geometric安装(CPU版本)

①打开官方安装网址&#xff1a;https://pytorch-geometric.readthedocs.io/en/2.3.0/install/installation.html ②对根据Pytorch选择相应版本。此前一直用CUDA不成功&#xff0c;这次使用CPU版本&#xff08;因为不用对应cuda&#xff0c;pytorchcudageometric三者对应起来很…

vue的跳转传参

在 Vue.js 中&#xff0c;进行页面跳转并传递参数通常涉及使用 Vue Router&#xff0c;这是 Vue.js 的官方路由库。以下是如何在 Vue Router 中进行页面跳转并传递参数的基本步骤 安装 Vue Router: 首先&#xff0c;你需要安装 Vue Router。你可以使用 npm 或 yarn 来进行安装…

[数据结构]动画详解单链表

&#x1f496;&#x1f496;&#x1f496;欢迎来到我的博客&#xff0c;我是anmory&#x1f496;&#x1f496;&#x1f496; 又和大家见面了 欢迎来到动画详解数据结构系列 用通俗易懂的动画的动画使数据结构可视化 先来自我推荐一波 个人网站欢迎访问以及捐款 推荐阅读 如何低…

微服务思想以及实现

文章目录 前言一、什么时候需要拆分微服务1. 创业型项目2. 大型项目 二、怎么拆1. 拆分目标2. 拆分方式 三、微服务之间远程调用1. 实现方式2. 手动发送Http请求&#xff08;RestTemplate&#xff09;3. 服务注册中心3.1 原理3.2 Nacos注册中心3.3 服务注册3.4 服务发现(Discov…

C语言中的静态库和动态库的制作和使用

什么是库文件 单一模型 将程序中所有功能全部实现于一个单一的源文件内部。 编译时间长&#xff0c;不易于维护和升级&#xff0c;不易于协作开发。 分离模型 将程序中的不同的功能模块划分到不同的源文件中。 缩短编译时间&#xff0c;易于维护和升级&#xff0c;易于协…

java spring 11 推断构造方法 createBeanInstance

1.doCreateBean方法&#xff1a;这一部分 BeanWrapper instanceWrapper null;if (mbd.isSingleton()) {// 有可能在本Bean创建之前&#xff0c;就有其他Bean把当前Bean给创建出来了&#xff08;比如依赖注入过程中&#xff09;instanceWrapper this.factoryBeanInstanceCache…

Open CASCADE 教程 – AIS:自定义呈现

文章目录 开始 (Getting Started)呈现构建器 (Presentation builders)基元数组 (Primitive arrays)基元外观 (Primitive aspects)二次构建器 (Quadric builders)计算选择 (Computing selection)突出显示选择所有者 (Highlighting selection owner)突出显示的方法 (Highlighting…

day10-Set集合

1.Set 那接下来我们来看Collection单列集合体系的第二部分 Set集合。 1.1 Set集合概述和特点 Set集合特点 1.可以去除重复 2.存取顺序不一致 3.没有带索引的方法&#xff0c;所以不能使用普通fori循环遍历&#xff0c;也不能通过索引来获取&#xff0c;删除Set集合里面的元…

【大数据】HDFS、HBase操作教程(含指令和JAVA API)

目录 1.前言 2.HDFS 2.1.指令操作 2.2.JAVA API 3.HBase 3.1.指令操作 3.2.JAVA API 1.前言 本文是作者大数据专栏系列的其中一篇&#xff0c;前文中已经详细聊过分布式文件系统HDFS和分布式数据库HBase了&#xff0c;本文将会是它们的实操讲解。 HDFS相关前文&#x…

Python 潮流周刊#50:我最喜欢的 Python 3.13 新特性!

本周刊由 Python猫 出品&#xff0c;精心筛选国内外的 250 信息源&#xff0c;为你挑选最值得分享的文章、教程、开源项目、软件工具、播客和视频、热门话题等内容。愿景&#xff1a;帮助所有读者精进 Python 技术&#xff0c;并增长职业和副业的收入。 本期分享了 12 篇文章&…

哈希算法在区块链中的应用

哈希算法是区块链技术的核心组件之一&#xff0c;它确保了区块链数据的不可篡改性和安全性。在本文中&#xff0c;我们将探讨哈希算法的基本原理&#xff0c;以及它在区块链中的具体应用。 哈希算法的基本原理 哈希算法是一种数学函数&#xff0c;它接收输入&#xff08;或“消…

【Apache Doris】周FAQ集锦:第 3 期

【Apache Doris】周FAQ集锦&#xff1a;第 3 期 SQL问题数据操作问题运维常见问题其它问题关于社区 欢迎查阅本周的 Apache Doris 社区 FAQ 栏目&#xff01; 在这个栏目中&#xff0c;每周将筛选社区反馈的热门问题和话题&#xff0c;重点回答并进行深入探讨。旨在为广大用户和…

【平台搭建+数据处理+数据可视化】

第一部分:大数据平台搭建 一、Hadoop 1、完全分布式Hadoop集群搭建: (1)在master主节点将/opt目录下的Hadoop安装包hadoop-3.1.4.tar.gz解压到/opt/software目录下。 mkdir -p /opt/software tar -zxf /opt/hadoop-3.1.4.tar.gz -C /opt/software (2)创建Hadoop临时数…

【每日随笔】人性 - 能屈能伸 ( 君子之道 能屈能伸 )

文章目录 一、君子之道 能屈能伸1、含义分析2、能屈3、能伸4、最佳实践 二、能屈能伸 - 应用场景1、个人层面2、国家层面 柳树随风摇曳 , 风再大也不会断 , 能屈能伸 ; 一个人行为处事 , 不能一直强硬 , 也不能一直妥协 , 该妥协的时候就要妥协让步 , 该硬的时候就要用于斗争 …

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-15.5讲 GPIO中断实验-通用中断驱动编写

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

学习Uni-app开发小程序Day8

前面几天&#xff0c;学习了vue的button组件、input组件&#xff0c;vue模版语法、计算属性等&#xff0c;在昨天又根据前面学习的&#xff0c;跟着做了一个小的购物车功能&#xff0c;今天学习了侦听器和计算属性 计算属性 computed computed是一个只读的状态,如果要修改…

Golang | Leetcode Golang题解之第77题组合

题目&#xff1a; 题解&#xff1a; func combine(n int, k int) (ans [][]int) {// 初始化// 将 temp 中 [0, k - 1] 每个位置 i 设置为 i 1&#xff0c;即 [0, k - 1] 存 [1, k]// 末尾加一位 n 1 作为哨兵temp : []int{}for i : 1; i < k; i {temp append(temp, i)}t…