【p2p】RTCPeerConnection协议理解
微wx笑 2022-11-05【前端开发】 3 0关键字: RTCPeerConnection p2p
一、SDPSDP全称是Session Description Protocol,翻译过来就是描述会话的协议。主要用于两个会话实体之间的媒体协商。SDP协议结构SDP描述由许多文本行组成,文本行的格式为<类
一、SDP
SDP全称是Session Description Protocol,翻译过来就是描述会话的协议。
主要用于两个会话实体之间的媒体协商。
SDP协议结构
SDP描述由许多文本行组成,
文本行的格式为<类型>=<值>,
<类型>是一个字母
<值>是结构化的文本串
SDP的 文本信息包括:
会话名称和意图描述
v = (协议版本)
o = (所有者/创建者和会话标识符)
s = (会话名称)
i = * (会话信息)
u = * (URI 描述)
e = * (Email 地址)
p = * (电话号码)
c = * (连接信息 ― 如果包含在所有媒体中,则不需要该字段)
b = * (带宽信息)
时间描述
t = (会话活动时间)
r = * (0或多次重复次数)
媒体描述
m = (媒体名称和传输地址)
i = * (媒体标题)
c = * (连接信息 — 如果包含在会话层则该字段可选)
b = * (带宽信息)
k = * (加密密钥)
a = * (0 个或多个会话属性行)
二、提议/应答(offer/answer)模型
1.提议
提议者产生一个 SDP 消息来描述它所期望的会话,这构成了一个提议(offer)。
提议中主要包括提议者想使用的媒体流和codecs集,以及提议者用于接收媒体的IP地址和端口。
2.应答
提议被传送到应答者,应答者可能会接受,也可能会拒绝这个提议。如果接收,应答者根据收到的提议和自身的能力产生一个SDP消息来描述它所能接受的会话,这称为应答(answer),应答中针对提议中的每个媒体流有一个匹配流,指示该媒体流是否被接受,同时伴随着要使用的codecs 和应答者希望用于接收媒体的 IP 地址和端口。
3.在提议/应答的操作中需遵守以下原则:
在任何时候,任何一方都可能产生一个新的提议来更新会话。然而,如果它收到了一个提议还没有应答或拒绝,则不能产生新的提议。
提议/应答交换是不可分的,如果应答被拒绝,会话恢复到提议前的状态。
提议 (和应答) 必须是RFC 2327 中所定义的有效SDP消息。尽管 SDP 规范允许将多个会话描述串接在一起形成一个大的 SDP 消息,但是在提议/应答模型中使用的SDP消息必须恰好包含一个会话描述。
在提议/应答模型中交换假定存在一个高层协议 (比如SIP),它能够完成SDP消息的交换,并能维持某种上下文关系,将一个提议及其应答,和创建和更新同一个会话的多个提议/应答对关联起来。
三、STUN 和 TURN
https://blog.csdn.net/u011077027/article/details/100496099
STUN(Session Traversal Utilities for NAT,NAT会话穿越应用程序):
(1)客户端找出自己的公网地址
(2)查出自己位于哪种类型的NAT之后
(3)以及NAT为某一个本地端口所绑定的Internet端端口。
这些信息被用来在两个同时处于 NAT路由器之后的主机之间建立UDP通信。
这个过程俗称NAT打洞或NAT穿越。
TURN(Traversal Using Relays around NAT,转发方式穿越NAT)是STUN的一个拓展,主要添加了转发功能。
如果终端在NAT之后, 那么在特定的情景下,有可能使得终端无法和其对等端(peer)进行直接的通信,这时就需要公网的服务器作为一个中继, 对来往的数据进行转发。
客户端通过发送Allocate请求给STUN服务器,从而让STUN服务器为A用户开启一个relay端口,可以看做是A的公网代理端口,TURN服务器就像代理服务器一样转发访问A用户的数据。
在STUN分配公网IP失败后,可以通过TURN服务器请求公网IP地址作为中继地址。
这种方式的带宽由服务器端承担,在多人视频聊天的时候,本地带宽压力较小。
四、ICEcandidate
ICEcandidate 用来表示远端通信的 protocol、ip、port
其中最主要的ICEcandidate的类型,分为下列三种类型:
● host 类型:本机内网,内网P2P连接
● srflx 类型:本机NAT映射后的外网,非对称型NAT网络环境,外网P2P连接
● relay 类型:一般是对称性NAT网络,需要走TURN中继服务器,无法建立P2P连接
其实 ICE 就是上面所讲的获取各种类型 Candidate 的过程,也就是:在本机收集所有的 host 类型的 Candidate,通过 STUN 协议收集 srflx 类型的 Candidate,使用 TURN 协议收集 relay 类型的 Candidate。
如果想确定自己浏览器里的webrtc客户端建立的是什么类型,可以通过chrome://webrtc-internals/查看
//示例: candidate: { candidate: 'a=candidate:138613430 1 udp 2122260223 10.10.10.232 61421 typ host generation 0 ufrag /9uN network-id 1 network-cost 10', sdpMid: '0', sdpMLineIndex: 0 } //说明: a: 会话属性行 candidate: 表明收到ICE候选者 138613430: 标志和区分来自同一个stun的不同的候选者,ID标识 1: ICE的组ID udp: 协议类型 2122260223:优先级priority 10.10.10.232:公网IP 61421: 公网IP转发的端口号 typ: 标识符,标识后面字段的属性类型是type host: 本地接口获取到的candidate,该字段还可以是(”host”, “srflx”, “prflx”, “relay”) generation 0: 代号,表明当前是第几代的候选 ufrag /9uN: ICE分配的用户名标识 network-id 1: 网卡标识 network-cost 10:
参考https://www.jianshu.com/p/1b00d73c93e7
host:本地接口获取到的candidate
srflx:NAT网关在公网侧的IP地址,通过STUN或者是TURN收集(server reflexive candidate)
prflx:可以在ICE的后续阶段中获取到(peer reflexive candidate)
relay:TURN服务器的公网转发地址,通过TURN收集(relayed candidate)
当TURN服务器启用时,两种地址都是从TURN服务器上获取到的。如果只有STUN服务器启用,那么只有server reflexive candidate可以从服务器获取到
var localConnection = new RTCPeerConnection(null, null);//创建一个RTCPeerConnection对象.对于SCTP,可靠且有序的交付默认为true。 var sendChannel = localConnection.createDataChannel('sendDataChannel', null); localConnection.onicecandidate = event=> {//网络候选变得可用时,调用此函数。 if (event.candidate) { localConnection.addIceCandidate( event.candidate ).then( ()=>console.log('AddIceCandidate1 success.',event.candidate), (e)=>console.log('Failed to add Ice Candidate: ',e) ) } } var remoteConnection = new RTCPeerConnection(null, null); remoteConnection.onicecandidate = event =>{ if (event.candidate) { localConnection.addIceCandidate( event.candidate ).then( ()=>console.log('AddIceCandidate success.'), (e)=>console.log('Failed to add Ice Candidate: ',e) ); } }; remoteConnection.ondatachannel = event=>{ var receiveChannel = event.channel; receiveChannel.onmessage = (event)=>console.log("receive:",event.data); }; localConnection.createOffer().then( desc =>{ localConnection.setLocalDescription(desc);//desc.sdp remoteConnection.setRemoteDescription(desc); remoteConnection.createAnswer().then( desc0 =>{ remoteConnection.setLocalDescription(desc0);//desc0.sdp localConnection.setRemoteDescription(desc0); }, e=>console.log(e) ) }, e=>console.log(e) ) sendChannel.onopen=(event)=>{ console.log("sendChannel.onopen",event) sendChannel.send(123); }
五、SDP与candidate
candidate描述一个页面。SDP描述两个页面之间的连接方式。
先协商SDP,然后再交换candidate
协商完成后会自动调用onicecandidate
RTCIceCandidate
address: "100.67.7.193" candidate: "candidate:100934627 1 udp 2122260223 100.67.7.193 49849 typ host generation 0 ufrag mIc8 network-id 1 network-cost 10" component: "rtp" foundation: "100934627" port: 49849 priority: 2122260223 protocol: "udp" relatedAddress: null relatedPort: null sdpMLineIndex: 0 sdpMid: "0" tcpType: null type: "host" usernameFragment: "mIc8"
RTCSessionDescription.sdp:
v=0 o=- 4475725184886384564 2 IN IP4 127.0.0.1 s=- t=0 0 a=group:BUNDLE 0 a=extmap-allow-mixed\r\na=msid-semantic: WMS m=application 9 UDP/DTLS/SCTP webrtc-datachannel c=IN IP4 0.0.0.0\r\na=ice-ufrag:mIc8 a=ice-pwd:Jbywz1ybw7WpxV0Jcu1HPEO2 a=ice-options:trickle a=fingerprint:sha-256 3C:89:81:1B:C4:43:39:64:7D:33:07:FA:D3:92:5F:6A:E4:8D:B2:86:A6:18:E1:A5:E7:29:90:AE:AC:31:30:65 a=setup:actpass a=mid:0 a=sctp-port:5000 a=max-message-size:262144 ```![在这里插入图片描述](https://img-blog.csdnimg.cn/64d96e29fc554b45b812321d64bd3fce.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQmlnIE9yYW5nZS4uLg==,size_14,color_FFFFFF,t_70,g_se,x_16) ![在这里插入图片描述](https://img-blog.csdnimg.cn/ccbcff0bd76f41639887198bf064d81b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQmlnIE9yYW5nZS4uLg==,size_20,color_FFFFFF,t_70,g_se,x_16)
本文为转载文章,版权归原作者所有,不代表本站立场和观点。