【音视频第14天】webRTC协议(1)

WebRTC连接机制:ICE,STUN,TURN与SDP详解
文章介绍了WebRTC如何通过ICE框架建立连接,包括NAT穿透的挑战和解决方案,如STUN和TURN服务器的作用。同时,详细阐述了SDP协议在描述会话内容和信令过程中的重要性,以及WebRTC如何使用SDP进行offer/answer模型的通信。

协议

ICE

Interactive Connectivity Establishment (ICE)是一个框架,能让web浏览器与对面进行连接。
从a端到b端不能直接建立连接原因有很多。

  1. 它需要绕过会阻止建立连接的防火墙
  2. 如果你的设备没有公共IP地址,那么它需要提供给你唯一的地址
  3. 如果你的路由器不允许直接与对端连接,那么需要通过服务器中转数据。
    ICE使用STUN和/或TURN服务器来完成此任务,如下所述。

STUN

Session Traversal Utilities for NAT (STUN)是一种协议,用于发现您的公共地址,并确定路由器中阻止与对端直接连接的任何限制。
客户端将向Internet上的STUN服务器发送一个请求,STUN服务器将回复客户端的公共地址以及在路由器的NAT之后是否可以访问客户端。
可以了就可以直接访问了。
在这里插入图片描述

NAT

Network Address Translation (NAT)用于为您的设备提供一个公共IP地址。路由器将有一个公共IP地址,连接到路由器的每个设备将有一个私有IP地址。请求将从设备的私有IP转换为路由器的具有唯一端口的公共IP。这样你就不用每个设备都有一个唯一的公共IP,但仍然可以在互联网上被发现。
对于谁能连接上已经在互联网上的设备,路由器对此有限制。这可能意味着,即使我们拥有STUN服务器找到的公共IP地址,也不是任何人都可以创建连接。在这种情况下,我们需要使用TURN。

TURN

一些使用NAT的路由器采用“对称NAT”的限制方法。这意味着路由器将只接受来自你之前连接过的对端的连接。【也就是在对称NAT下,只能连接之前连接了的对端】
Traversal Using Relays around NAT (TURN)意味着绕过对称NAT的限制,通过打开与TURN服务器的连接并通过该服务器中转所有信息。您将创建一个与TURN服务器的连接,并告诉所有对等点向服务器发送数据包,然后这些数据包将被转发给您。这显然会带来一些成本开销,所以只有在没有其他替代方案的情况下才会使用它。
在这里插入图片描述

SDP

Session Description Protocol (SDP)是一种标准,用于描述连接的多媒体内容,如分辨率、格式、编解码器、加密等,以便对等端在数据传输时能够相互理解。从本质上讲,这是描述内容的元数据,而不是媒体内容本身。
从技术上讲,SDP并不是真正的协议,而是一种用于描述设备间共享媒体的连接的数据格式
编写SDP文档远远超出了本文档的范围;然而,这里有一些事情值得注意:

SDP结构

SDP由一行或多行UTF-8文本组成,每行以一个字符类型开头,后面跟着等号(“=”),然后是包含值或描述的结构化文本,其格式取决于类型。以给定字母开头的文本行通常被称为“字母行”。例如,提供媒体描述的行具有“m”类型,因此这些行被称为“m-line”。

Signaling and Connecting

Signaling: How peers find each other in WebRTC

【通过带外的信令,传递SDP】
当WebRTC代理启动时,它不知道它要与谁通信,也不知道他们要通信什么。Signaling解决了这个问题。Signaling用于引导调用,允许两个独立的WebRTC代理开始通信。
Signaling使用一种称为SDP(会话描述协议)的协议。每个SDP消息由键/值对组成,并包含一个“media sections”列表。两个WebRTC代理交换的SDP包含如下细节:

  • 代理可访问的ip和ports
  • 代理希望发送的音频和视频轨道的数量。
  • 每个代理支持的音频和视频编解码器。
  • 连接时使用的值(uFrag/uPwd)。
  • 安全时使用的值(证书指纹)。
    需要注意的是,信令通常发生在“带外out-of-band”,这意味着应用程序通常不使用WebRTC本身来交换信令消息。任何适合于发送消息的体系结构都可以在连接的对等体之间中转sdp,许多应用程序将简单地使用它们现有的基础结构(例如REST端点、WebSocket连接或身份验证代理)来促进适当的客户机之间的sdp交易。

Connecting and NAT Traversal with STUN/TURN

【通过ICE建立连接】
一旦两个WebRTC代理交换了sdp,它们就有了足够的信息来尝试相互连接。为了实现这种连接,WebRTC使用了另一种称为ICE(交互式连接建立)的成熟技术。
ICE是一种早于WebRTC的协议,允许在没有中央服务器的情况下在两个代理之间建立直接连接。这两个代理可能在同一个网络上,也可能在世界的另一端。
ICE可以实现直接连接,但真正连接过程涉及一个叫做“NAT遍历”的概念和STUN/TURN服务器的使用。
当两个代理成功建立ICE连接时,WebRTC将进入下一步;为在它们之间共享音频、视频和数据建立加密传输。

Signaling

当您创建WebRTC代理时,它对另一个对端一无所知。它不知道它将与谁连接,也不知道他们将发送什么。我们使用信令引导调用。在这些值交换之后,WebRTC代理可以直接相互通信。信令信息只是文本。WebRTC并不关心他们是如何被运输的。它们通常通过Websockets共享,但这不是必需的。
WebRTC使用一种称为sdp协议。通过该协议,两个WebRTC端点将共享建立连接所需的所有状态。协议本身易于阅读和理解。复杂性来自于理解WebRTC填充的所有值**。这个协议不是专门针对WebRTC的**。WebRTC实际上只利用了sdp协议的一个子集,所以我们只学习我们需要的部分。在我们理解该协议之后,我们将继续讨论它在WebRTC中的应用。

sdp协议

sdp协议在RFC 8866中定义。它是一个键/值协议,每个值后面都有换行符。它感觉类似于INI文件。一个会话描述包含0个或多个媒体描述。在思想上,你可以把它建模为一个会话描述,其中包含一个媒体描述数组。
媒体描述通常映射到一个单一的媒体流。因此,如果你想用三个视频流和两个音频轨道来描述一个会话,你将有五个媒体描述。
会话描述中的每一行都以一个字符开始,这是你的键。然后它后面会跟着一个等号。等号后面就是值。在该值完成后,将有一个换行符。
会话描述协议定义了所有有效的密钥。您只能使用协议中定义的字母作为密钥。这些键都有重要的意义,后面会解释。以下会话描述:

a=my-sdp-value
a=second-value

你有两条线。第一行值为my-sdp-value,第二行值为second-value。
WebRTC并不使用会话描述协议定义的所有键值。只有在RFC 8829中定义的JavaScript会话建立协议(JSEP)中使用的键是重要的。下面的七个关键是你现在只需要了解的:

v - Version, should be equal to 0.
o - Origin, 包含一个唯一的ID,用于重新协商.
s - Session Name, should be equal to -.
t - Timing, should be equal to 0 0.
m - Media Description (m=<media> <port> <proto> <fmt> ...), described in detail below.
a - Attribute, 一个自由文本字段。这是WebRTC中最常见的一行。
c - Connection Data, should be equal to IN IP4 0.0.0.0.

“会话描述”可以包含无限个“Media Description”。
Media Description定义包含一个格式列表。这些格式映射到RTP有效负载类型。然后,实际的编解码器由Media Description中值为rtpmap的Attribute定义。每个媒体描述可以包含无限数量的属性。
以这段Session Description摘录为例:

v=0
m=audio 4000 RTP/AVP 111
a=rtpmap:111 OPUS/48000/2
m=video 4000 RTP/AVP 96
a=rtpmap:96 VP8/90000
a=my-sdp-value

您有两个媒体描述,一个是fmt 111类型的音频,一个是96格式的视频。第一个媒体描述只有一个属性。此属性将负载类型111映射到Opus。第二个Media Description有两个属性。第一个属性将Payload Type 96映射为VP8,第二个属性是my-sdp-value。
下面将我们讨论过的所有概念结合在一起。这些都是WebRTC使用的会话描述协议的所有特性。

v=0
o=- 0 0 IN IP4 127.0.0.1
s=-
c=IN IP4 127.0.0.1
t=0 0
m=audio 4000 RTP/AVP 111
a=rtpmap:111 OPUS/48000/2
m=video 4002 RTP/AVP 96
a=rtpmap:96 VP8/90000

v, o, s, c, t被定义,但它们不影响WebRTC会话。
你有两个媒体描述。一个是音频类型,一个是视频类型。
每一个都有一个属性。此属性配置RTP管道的详细信息。

WebRTC如何使用sdp

WebRTC使用offer/answer模型。这意味着一个WebRTC代理发出“offer”开始呼叫,如果它愿意接受所提供的内容,WebRTC 另一端“answers”。这使应答者有机会在媒体描述中拒绝不支持的编解码器。这就是两端如何理解它们想交换的格式。
Transceivers 是用于发送和接收的
Transceivers 是WebRTC特定的概念,你将在API中看到。它将“Media Description”暴露给JavaScript API。每个Media Description都成为一个Transceivers。每次你创建一个Transceivers,一个新的“Media Description就会被添加到本地Session Description中。WebRTC中的每个Media Description都有一个方向属性。这允许WebRTC代理声明“我将把这个编解码器发送给你,但我不愿意接受任何回报”。有四个有效值:send recv sendrecv inactive
WebRTC使用的SDP值
在WebRTC代理的会话描述中常见属性的列表。这些值控制着子系统。
group:BUNDLE:Bundling是在一个连接上运行多种类型的流量的行为。一些WebRTC实现为每个媒体流使用专用连接。最好是Bundling。
fingerprint:sha-256:这是对等体用于DTLS的证书的hash。DTLS握手完成后,将其与实际证书进行比较,以确认您正在与期望的对象通信。
**setup:**这控制DTLS代理行为。这决定了在ICE连接之后,它是作为客户机还是服务器运行。可能取值为:

  • setup:active -作为DTLS客户端运行。
  • setup:passive -作为DTLS服务器运行。
  • setup:actpass -让其他WebRTC代理选择。
    **mid:**识别会话描述中的媒体流。
    ice-ufrag:这是ICE Agent的用户分片值。用于对ICE Traffic进行认证。
    ice-pwd:这是 ICE Agent的密码。用于对ICE Traffic进行认证。
    rtpmap:此值用于将特定的编解码器映射到RTP有效负载类型。有效负载类型不是静态的,因此对于每个调用,提供程序决定每个编解码器的有效负载类型。
    fmtp:为一个有效负载类型定义附加值。这对于传达特定的视频配置文件或编码器设置非常有用。
    **candidate:**这是一个来自ICE Agent的ICE Candidate。这是WebRTC Agent 可用的一个可能地址。这些将在下一章详细解释。
    ssrc :一个同步源(SSRC)定义了一个单一的媒体流轨迹。
    label:是这个单独流的ID。mslabel是容器的ID,容器里面其中可以有多个流。

WebRTC会话示例

下面是WebRTC客户端生成的完整会话描述:

v=0
o=- 3546004397921447048 1596742744 IN IP4 0.0.0.0
s=-
t=0 0
a=fingerprint:sha-256 0F:74:31:25:CB:A2:13:EC:28:6F:6D:2C:61:FF:5D:C2:BC:B9:DB:3D:98:14:8D:1A:BB:EA:33:0C:A4:60:A8:8E
a=group:BUNDLE 0 1
m=audio 9 UDP/TLS/RTP/SAVPF 111
c=IN IP4 0.0.0.0
a=setup:active
a=mid:0
a=ice-ufrag:CsxzEWmoKpJyscFj
a=ice-pwd:mktpbhgREmjEwUFSIJyPINPUhgDqJlSd
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10;useinbandfec=1
a=ssrc:350842737 cname:yvKPspsHcYcwGFTw
a=ssrc:350842737 msid:yvKPspsHcYcwGFTw DfQnKjQQuwceLFdV
a=ssrc:350842737 mslabel:yvKPspsHcYcwGFTw
a=ssrc:350842737 label:DfQnKjQQuwceLFdV
a=msid:yvKPspsHcYcwGFTw DfQnKjQQuwceLFdV
a=sendrecv
a=candidate:foundation 1 udp 2130706431 192.168.1.1 53165 typ host generation 0
a=candidate:foundation 2 udp 2130706431 192.168.1.1 53165 typ host generation 0
a=candidate:foundation 1 udp 1694498815 1.2.3.4 57336 typ srflx raddr 0.0.0.0 rport 57336 generation 0
a=candidate:foundation 2 udp 1694498815 1.2.3.4 57336 typ srflx raddr 0.0.0.0 rport 57336 generation 0
a=end-of-candidates
m=video 9 UDP/TLS/RTP/SAVPF 96
c=IN IP4 0.0.0.0
a=setup:active
a=mid:1
a=ice-ufrag:CsxzEWmoKpJyscFj
a=ice-pwd:mktpbhgREmjEwUFSIJyPINPUhgDqJlSd
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:96 VP8/90000
a=ssrc:2180035812 cname:XHbOTNRFnLtesHwJ
a=ssrc:2180035812 msid:XHbOTNRFnLtesHwJ JgtwEhBWNEiOnhuW
a=ssrc:2180035812 mslabel:XHbOTNRFnLtesHwJ
a=ssrc:2180035812 label:JgtwEhBWNEiOnhuW
a=msid:XHbOTNRFnLtesHwJ JgtwEhBWNEiOnhuW
a=sendrecv

以下是我们从这条信息中了解到的:
我们有两个媒体部分,一个音频部分和一个视频部分。
它们都是sendrecv收发器。我们得到了两个流,我们可以发送两个回去。
我们有ICE候选人和身份验证详细信息,因此我们可以尝试连接。
我们有一个证书指纹,所以我们可以进行安全通话。

Connecting

为什么WebRTC需要一个专用的子系统来连接?

目前部署的大多数应用程序都建立 client/server连接。客户端/服务器连接要求服务器有一个稳定的已知传输地址。客户端与服务器连接,服务器响应。

WebRTC不使用 client/server 模型,它建立点对点(P2P)连接。在P2P连接中,创建连接的任务平均分配给两端。这是因为WebRTC中的传输地址(IP和端口)不能被假定,甚至可能在会话期间发生变化。WebRTC将尽可能地收集所有信息,并将竭尽全力实现两个WebRTC代理之间的双向通信。

不过,建立点对点连接可能很困难。这些代理可能位于不能直连的不同网络中。在存在直连的情况下,您仍然可能遇到其他问题。在某些情况下,您的客户端不使用相同的网络协议(UDP <-> TCP)或可能使用不同的IP版本(IPv4 <-> IPv6)

尽管在建立P2P连接时存在这些困难,但由于WebRTC提供的以下属性,您获得了优于传统客户端/服务器技术的优势。

  1. Reduced Bandwidth Costs
    因为媒体通信直接发生在对等点之间,你不需要付费,也不需要托管一个单独的服务器来转发媒体。
  2. Lower Latency
    低延迟:Lower Latency
    直连更快捷,当通过服务器运行所有内容时,传输速度会变慢
    3.Secure E2E Communication
    端到端安全通信:直接交流更安全。由于用户不会通过您的服务器路由数据,因此他们甚至不需要相信您不会解密数据

上面描述的过程称为交互式连接建立(ICE)。另一个早于WebRTC的协议。ICE是一种试图找到两个ICE代理之间通信的最佳方式的协议。每个ICE Agent 公布了可以到达的方式,这些被称为candidates。candidates本质上是agent的传输地址,它认为另一个对端可以到达该传输地址。然后,ICE决定candidates的最佳组合。

Networking real-world constraints

ICE就是要克服现实世界网络的限制。在探讨解决方案之前,让我们先谈谈实际问题

  1. 不在同一个网络
    在这里插入图片描述
    对于同一网络中的主机来说,连接非常容易。192.168.0.1 ->192.168.0.2很容易做到。这两台主机可以在没有任何外部帮助的情况下相互连接。
    然而,使用路由器B(routerB)的主机没有办法直接访问路由器a(routerA)后面的任何东西,你如何区分路由器a(routerA)后面的192.168.0.1和路由器B(routerB)后面的相同IP ? 它们是私有ip 。使用路由器B(routerB)的主机可以直接向路由器A(routerA)发送流量,但请求将在那里结束。路由器A(routerA)如何知道它应该把消息转发给哪台主机?
  2. 协议限制
    一些网络根本不允许UDP流量,或者可能他们不允许TCP。一些网络可能有非常低的MTU(最大传输单元)。网络管理员可以改变很多变量,从而使通信变得困难。
  3. 防火墙/IDS规则
    另一个是“深度包检测”和其他智能过滤。一些网络管理员会运行试图处理每个数据包的软件。很多时候,这个软件不理解WebRTC,所以它会阻止它,因为它不知道该做什么,例如,将WebRTC数据包视为任意端口上的可疑UDP数据包,而不是白名单。

NAT Mapping

NAT(网络地址转换)映射是使WebRTC的连通性成为可能。这就是WebRTC允许完全不同子网中的两端通信的方式,解决了上述“不在同一个网络”的问题。虽然Agent 1和Agent 2他们在不同的网络中,但是是可以通信的。
在这里插入图片描述
为了实现这种通信,需要建立一个NAT映射。Agent 1通过7000端口与Agent 2建立WebRTC连接。这将创建192.168.0.1:7000到5.0.0.1:7000的绑定。这允许Agent 2通过发送到5.0.0.1:7000的报文到达Agent 1。这个示例中的NAT映射就像在路由器中进行端口转发的自动版本。

NAT映射的缺点是没有单一形式的映射(例如静态端口转发),并且网络之间的行为不一致。互联网服务提供商和硬件制造商可能以不同的方式做到这一点。【看不太懂NAT映射的缺点】在某些情况下,网络管理员甚至会禁用它。好消息是,所有的行为都是可以理解和观察到的,因此ICE代理能够确认它创建了一个NAT映射,以及映射的属性。描述这些行为的文档是RFC 4787。

创建映射

创建映射是最简单的部分。当你发送一个包到你的网络之外的地址时,一个映射就被创建了。NAT映射只是一个临时的公网IP和端口,由您的NAT分配。出站消息将被重写,其源地址由新的映射地址给出。如果一条消息被发送到映射,它将自动路由回创建它的NAT内的主机。映射的细节是它变得复杂的地方。

映射创建行为

映射创建分为三个不同的类别:

  1. 端点独立映射
    在NAT内部为每个发送方创建一个映射。如果向两个不同的远端地址发送两个报文,NAT映射将被重用。两个远程主机将看到相同的源IP和端口。如果远程主机响应,它将被发送回同一个本地侦听器。
    这是最好的情况。对于工作调用,至少有一方必须是这种类型。
  2. 地址依赖映射
    每次发送一个数据包到一个新地址时都会创建一个新的映射。如果向不同的主机发送两个报文,会产生两个映射。如果向同一个远端主机发送两个数据包,但目的端口不同,则不会创建新的映射。
  3. 地址和端口依赖映射
    如果远端IP或端口不同,则创建新的映射。如果向同一个远端主机发送两个数据包,但目的端口不同,则会创建一个新的映射。

映射过滤行为

映射过滤是关于谁可以使用映射的规则。它们分为三个类似的类别:

  1. 端点独立过滤
    任何人都可以使用映射。您可以与多个其他对等点共享映射,它们都可以向它发送流量。
  2. 地址相关过滤
    只有创建映射的主机可以使用该映射。如果您向主机A发送数据包,则只能从同一主机获得响应。如果主机B试图向该映射发送一个数据包,它将被忽略。
  3. 地址和端口依赖过滤
    只有为其创建映射的主机和端口才能使用该映射。如果你发送一个包到a:5000,你只能从同一个主机和端口得到响应。如果A:5001试图向该映射发送一个数据包,它将被忽略。

映射刷新

如果一个映射5分钟没有使用,建议销毁它。这完全取决于ISP或硬件制造商。

STUN

STUN(NAT 会话传输实用程序)是一种用来配合 NAT 使用的协议。这是 WebRTC(和 ICE!)之前的另一项技术。它由RFC 8489定义,该文件还定义了 STUN 数据包结构。STUN 协议也在 ICE/TURN 中被使用。

STUN 很有用,因为它允许以编程方式创建 NAT 映射。在 STUN 之前,我们能够创建 NAT 映射,但是我们不知道映射的 IP 和端口是什么!STUN 不仅使你能够创建映射,还可以让你获取映射的详细信息,你可以他人分享这些详细信息,然后他们便可以通过你刚刚创建的映射向你传回数据。

让我们从对 STUN 的基本描述开始。稍后,我们再将话题扩展到 TURN 和 ICE 的用法。现在,我们只打算描述请求 / 响应流程来创建映射。然后,我们将讨论如何获取该映射的详细信息以便与他人共享。当你在 ICE URLs 中有一个用于 WebRTC PeerConnection 的 stun: 服务器时,此过程就会发生。简而言之,STUN 向 NAT 外部的 STUN 服务器发送请求,服务器返回其在请求中观察到的内容,STUN 根据这些内容来帮助 NAT 后面的端点找出已创建的映射。

Protocol Structure

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0|     STUN Message Type     |         Message Length        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         Magic Cookie                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
|                     Transaction ID (96 bits)                  |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                             Data                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

STUN 消息类型
每个 STUN 数据包都有一个类型。目前,我们仅关心以下几种:

  • Binding Request - 0x0001
  • Binding Response - 0x0101
    为了创建一个 NAT 映射,我们发出一个 Binding Request。然后服务器回应一个 Binding Response

消息长度
这就是 Data 段的长度。这一段中包含由消息类型所定义的任意数据。

Magic Cookie
指的是固定值 0x2112A442,以网络字节顺序发送。这个值有助于将 STUN 流量与其他协议区分开。

交互(Transaction)ID
一个 96-bit 的标识符,用于唯一标识一个请求 / 响应对。这可以帮助你配对请求和响应。

数据
数据将包含一个 STUN 属性的列表。一个 STUN 属性具有以下结构:

0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         Type                  |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         Value (variable)                ....
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

STUN Binding Request 不使用任何属性。这意味着一个STUN Binding Request仅包含 header。

STUN Binding Response 使用一个 XOR-MAPPED-ADDRESS (0x0020)。此属性包含一个 IP 和一个端口。这正是所创建的 NAT 映射的 IP 和端口!

创建 NAT 映射

使用 STUN 创建 NAT 映射只需要发送一个请求。你向 STUN 服务器发送一个 STUN Binding Request。然后,STUN 服务器回应一个 STUN Binding Response。 该 STUN Binding Response 将包含映射地址。映射地址是 STUN 服务器看到你的方式,也是你的 NAT 映射。 如果你希望某人向你发送数据包,那么你应该共享该映射地址。

人们还会将映射地址称为公网 IP 或 Server Reflexive Candidate。

确定 NAT 类型

不幸的是,映射地址可能并非在所有情况下都可用。如果是地址相关的映射,则只有 STUN 服务器才能将流量发送回给你。如果你共享它,那么另一个 peer 尝试向该地址发送的消息将被丢弃。这使得该 peer 无法与别的 peer 交流。如果 STUN 服务器还可以为你将数据包转发给对端 peer,你可能会发现地址相关的映射问题实际上是可以解决的!这也就是下面将要说到的 TURN 解决方案。

RFC 5780定义了一种方法,可以运行一个测试来确定你的 NAT 类型。这很有用,因为你可能会提前知道是否可以进行直接连接。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值