1       说明

2       打洞和穿越的概念... 1

3       P2P中的打洞和穿越... 2

4       使用STUN系列 协议穿越的特点... 2

5       STUN/ TURN/ICE协议的关系... 3

6       STUN协议(RFC 5389) 3

6.1             为什么会用到STUN协议... 3

6.2             STUN协议的工作原理... 4

7       TURN协议... 4

7.1             为什么会用到TURN协议... 4

7.2             TURN协议的工作原理... 5

7.2.1         Allocate请求... 5

7.2.2         Relay端口消息的转发... 6

7.2.2.1    A的Relay端口接受其他客户端的消息... 6

7.2.2.2    A的响应消息原路返回... 6

7.2.2.3     思考... 7

7.2.3         Refresh请求... 7

7.2.4         STUN端口的保活... 8

7.2.5         Relay转发的时候添加STUN头(Send和Data请求)... 8

7.2.6         使用TURN协议的必要性... 9

8       ICE协议... 9

8.1             打洞原理... 9

8.2             ICE的打洞... 10

8.3             ICE的打洞的4次握手... 11

8.4             ICE扩展的Binding消息... 12

8.5             REGULAR NOMINATION 和 AGGRESSIVE NOMINATION.. 12

8.6             Peer Reflexive. 13

8.6.1         Peer Reflexive Candidates的概念... 13

8.6.2         Peer Reflexive Candidates的发现... 13

8.6.2.1     当通信双方处在不同层次的NAT下的情况... 14

8.6.2.2     与NAT的类型相关... ...15

8.6.2.3     其他情况... ...16

8.6.2.4     公网P2P中的Peer Reflexive. ...16

9       ICE在SIP中的应用... 16

9.1             呼叫双方分别收集3组地址...... 17

9.1             A发送INVITE给B. ...18

9.2             B给A回100、101、180. ...18

9.3             B给A回200 ok. ...19

9.4             A给B回ACK   ...19

上个礼拜写了第1、2、3、4、5,今天把6、7也写完了,另外也总结了第8和第9,准备再分两次发布。

关于第1、2、3、4、5 请查看:STUN/TURN/ICE协议在P2P SIP中的应用(一)

本次书接上回,现在开始。

---------------------------------------------------------------------------------------------------------------------------

6           STUN协议(RFC 5389)

6.1          为什么会用到STUN协议

首先要明确的概念是:STUN协议没有穿越的能力,它只是为穿越提供反射地址(Server Reflexive Address)。在双方进行通讯的时候,我们双方的目的地址可以分别为对方的反射地址,但是反射地址不能穿越成功的时候(NAT类型为对称类型的时候),必须使用TURN。

本文所说的STUN协议指的是RFC(5389) ,RFC(5389)已经移除了NAT类型探测的能力(RFC(3489)定义了NAT类型探测的能力),STUN协议主要有2个功能:

  • 让一个位于NAT后的客户端得到自己的公网地址(反射地址,Server Reflexive Address),该功能通过向服务端发送一个 Binding请求,服务端返回一个success response消息来完成。success response消息中包含一个叫做XOR-MAPPED-ADDRESS的属性,该属性的值就是“反射地址”经过异或后的值
  • 在ICE(交互式连接建立)时,用于探测双方的连通性。该功能也是通过向对方客户端发送Binding消息,对方响应该请求实现。需要说明一点的是,在ICE交互时的Binding消息与1中所说的Binding消息不一样。ICE添加了几个新的属性,从而扩展了Binding消息:PRIORITY, USE-CANDIDATE, ICE-CONTROLLED, ICE-CONTROLLING。这种扩展了的Binding消息,只会用在ICE的探测中。

6.2          STUN协议的工作原理

A.     客户端用于得到自己的外网地址(反射地址,Server Reflexive Address),如下图所示

a)         客户端A向STUN Port发送Binding请求(图中绿色部分)

b)        STUN服务器接收到客户端A的Binding请求,它能得到该请求的源地址与端口(该地址和端口就是经过NAT映射过的),将该地址和端口记为Server Reflexive Address。

c)         STUN服务器发送response响应,在response响应中携将Server Reflexive Address经过异或后填入XOR-MAPPED-ADDRESS属性。

d)         客户端A接受到STUN服务器的response后,就知道了自己的外网地址(反射地址,Server Reflexive Address)。

B.      在ICE(交互式连接建立)是,用于双方的连通性探测。

在ICE打洞探测的时候再详细介绍

7           TURN协议

7.1          为什么会用到TURN协议

前面也提到过,TURN协议是STUN 协议的有效补充,在使用反射地址(Server Reflexive Address)穿越方式失败的时候才会用到TURN。

简单的说就是,TURN协议使用中转的方式实现位于两个不同NAT后的客户端通信。TURN协议为每个连接到该服务器的客户端都分配一个公网地址(Relayed  Address),该Relayed地址专门为该客户端中转消息。

该方法是实现位于两个不同NAT后的客户端通信的一个方式(其他方式还有p2p)。

该方法的优点是:不管NAT是什么类型(NAT类型分为:全锥形、地址限制锥形、端口限制锥形、对称型),都可以通过这种方式实现两个客户端的通信。

该方法的弊端有两个:

  1. 第一个是,如果通信两端传输的数据量过大(比如客户端之间传输的是音视频),那么每个数据包都要经过TURN服务器的转发,那么会造成数据的丢失以及传送时延的增加;
  2. 第二个是,成本问题,如果每两个客户端之间的通信都要经过TURN转发,那么在客户端到达一定规模后(十万上百万),需要架设大量的TURN服务器。这在成本上是无法承受的。所以才有了使用P2P方式。需要说明的有一点,双方可以进行点对点的直接通信,不是因为它们之间点对点通信后丢包和时延问题就能解决(P2P方式也可能有比较大的丢包),而是成本问题。

所以这种使用TURN协议中转的方式只会用在双方通信交互内容数据量较少的情况下。

7.2          TURN协议的工作原理

本节描述了TURN协议的大体工作原理,与RFC 5766有一定的出入,了解了此工作原理再去看RFC 5766 会事半功倍。本节介绍不涉及到RFC 5766中提到的,CreatePermission、ChannelBind操作。

7.2.1          Allocate请求

客户端通过发送Allocate请求给STUN服务器,从而让STUN服务器为A用户开启一个relay端口。

a)         客户端A向STUN Port发送Allocate请求(图中绿色部分)

       b)        STUN服务器接收到客户端A的Allocate请求,服务器一看是Allocate请求,则根据relay端口分配策略为A分配一个端口。

c)         服务器发送response成功响应。在该response中包含XOR-RELAYED-ADDRESS属性。该属性值就是A的relay端口的异或结果。

d)         客户端接收到response后,就知道了自己的relay地址。该relay地址是个公网地址,可以看作是客户端A在公网上的一个代理,任何想要联系A的客户       端,只要将数据发送到A的relay地址就可以了,具体的转发原理请看下一小节。

7.2.2          Relay端口消息的转发

任何想要联系客户端A的人,只要知道客户端A的relay地址就可以了。

7.2.2.1         A的Relay端口接受其他客户端的消息

如上图所示:因为客户端A位于NAT后,所以其他客户端无法和A建立直接的通信。但是客户端A在STUN服务器上申请了一个端口(上图中:A的relay端口),其他客户端想要和A通信,那么只需要将信息发送到“A的relay端口”,STUN服务器会将从relay端口接收到的信息通过STUN Port发送给A。

7.2.2.2         A的响应消息原路返回

A应答其他客户端发来的消息的时候,是通过原路返回的。

7.2.2.3         思考

1.STUN服务器为什么不直接从A的relay端口把数据转发给A呢(如下图所示)?而非要从STUN端口发送?

2.客户端A的响应消息在原路返回的时候,A的响应消息是先发送到了STUN Port,然后再经由A的relay Port发出的。那么A的relay Port是怎么知道它要把数据发送到哪呢?

请看7.2.4 和 7.2.5

7.2.3          Refresh请求

STUN服务器给客户端A分配的relay地址都具有一定的有效时长,可能是30秒或者1分钟或者几十分钟。客户端如果需要STUN服务器一直为它开启这个端口,就需要定时的向STUN服务器发送请求,该请求用刷新relay端口的剩余时间。

在标准的TURN(RFC 5766)协议中,客户端A向STUN服务器发送Allocate请求,STUN服务器在响应消息中添加了一个“LifeTime”的属性,该属性表示relay的存活时间。 客户端需要在relay的存活时间内周期性的调用REFRESH请求,服务端接收到REFRESH请求后,刷新剩余时间;当REFRESH请求中的lifetime属性为0时,说明是客户端主动要求关闭relay地址。

7.2.4          STUN端口的保活

由于与STUN服务器通信使用的是UDP,所以为了保持一个长连接,需要客户端周期性的向STUN服务器的STUN Port发送心跳包。

周期性心跳包的目的就是,使得NAT设备对客户端A的反射地址(Server Reflexive Address)一直有效。使得从STUN Port发送的数据能通过A的反射地址到达A。此处不理解的可以查阅“NAT 类型的分类以及NAT的作用”。

此处解释了,7.2.2.3中的第一个问题,因为客户端A没有和relay Port保活,又由于NAT的特性,数据直接通过relay port转发给A时,NAT直接就丢弃了,所以A是收不到的。所以数据必须经过STUN服务器的STUN  Port发送。

7.2.5          Relay转发的时候添加STUN头(Send和Data请求)

将7.2.2.1、 7.2.2.2合并到一起就是:

如上图所示是B主动给A发消息:“Hello”,A回应“Hi”的过程。

序号1、2、3、4、5为B的发送请求(蓝色箭头方向);

序号6、7、8、9、10为A的回应,原路返回(绿色箭头方向)。

注意:在“Hello”发送的过程中,1、2阶段时,发送的数据为裸的UDP数据。在4、5过程中,是被STUN协议包装过的“Hello”,称之为Data indication。

同样在“Hi”发送的过程中,6、7阶段为被STUN协议包装过的“Hi”,称之为Send indication,9、10是裸的UDP数据。

在4、5阶段,由于数据是从STUN Port转发下来的,为了能够让客户端A知道这个包是哪个客户端发来的,所以,STUN 协议对“Hello”进行了重新的包装,最主要的就是添加了一个XOR-PEER-ADDRESS属性,由裸数据包装成STUN协议的过程,我们称之为添加了STUN头。XOR-PEER-ADDRESS的内容就是客户端B的反射地址(Server Reflexive Address)。

在6、7阶段,A的响应原路返回,为了能够让A的relay port知道最终发往哪个客户端,因此也为“Hi”添加了STUN头,也是添加了XOR-PEER-ADDRESS属性,内容就是客户端B的反射地址(Server Reflexive Address)。这样A的relay port就知道“Hi”的目的地址。

第3阶段是:从A的relay端口收到数据,添加STUN头后,最后从STUN Port 发出的过程。

第8阶段是:从STUN Port 接收到带STUN 头的数据,去掉STUN头,最后从A的relay端口发出的过程。

此处解释了7.2.2.3 的第二个问题。

客户端B主动发送信息给A的交互流程如上图所示,那么客户端A主动发送信息给客户端B的交互流程是怎样的呢,你能画出来吗?

要知道客户端A主动发消息给客户端B,应该将消息发往客户端B的relay port哦。。

7.2.6          使用TURN协议的必要性

要想实现消息的中转,必须使用TURN协议吗?答案当然是否定的。

TURN协议只是一种公认的,标准的协议。我们当然可以实现自己的协议,但是已经有人对标准的TURN协议进行了实现(比如pjproject,它实现了STUN、TURN、ICE、SIP),我们为什么不拿来就用呢?

在拿来就用的过程中,肯定会对已经实现的标准做一定的改动。但这关系不大,实现我们所关注的功能即可。

本文为原创,转载请注明以下内容:

  名称:STUN/TURN/ICE协议在P2P SIP中的应用(二)

  作者:大雪先生

  链接:http://www.cnblogs.com/ishangs/p/3816689.html

最新文章

  1. useful commands for Kubernetes beginners
  2. 如何使用openssl生成RSA公钥和私钥对
  3. 129. Sum Root to Leaf Numbers
  4. rsyncd.conf 文件
  5. 项目中用到的SQL-总结
  6. js如何判断一个对象是不是Array
  7. jQuery选择器之全面总结
  8. css ul li 制作导航条
  9. 进程间通信之FIFO
  10. [java线段树]2015上海邀请赛 D Doom
  11. C++语言体系设计哲学的一些随想(未完待续)
  12. google反向代理网址收集
  13. Java疯狂讲义(三)
  14. HDU 5867 Water problem
  15. WebApi接口请求失败,找不到资源。
  16. mysql 学习心得5
  17. volitale、synchronized、RetreenLock区别
  18. Android Studio NDK JNI动态注册本地方法
  19. Ubuntu下搭建tftp服务器最简单方法
  20. Atitit 提升效率 界面gui方面的前后端分离与cbb体系建设 规范与推荐标准

热门文章

  1. Kth Ancestor 第k个祖先问题
  2. How to Validate XML using Java
  3. Spring学习总结
  4. php 获取某个月的周次信息
  5. LabSharp莱博夏普简介
  6. 了解node.js
  7. wpf DataGrid CheckBox列全选
  8. 全文索引(三)lucene 分词 Analyzer
  9. 对MYSQL IFNULL函数的使用进行了具体的叙述
  10. java多线程样例