客户端经过发送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地址就能够了,具体的转发原理请看下一小节。服务器
任何想要联系客户端A的人,只要知道客户端A的relay地址就能够了。flex
如上图所示:由于客户端A位于NAT后,因此其余客户端没法和A创建直接的通讯。可是客户端A在STUN服务器上申请了一个端口(上图中:A的relay端口),其余客户端想要和A通讯,那么只须要将信息发送到“A的relay端口”,STUN服务器会将从relay端口接收到的信息经过STUN Port发送给A。代理
A应答其余客户端发来的消息的时候,是经过原路返回的。code
思考
1.STUN服务器为何不直接从A的relay端口把数据转发给A呢(以下图所示)?而非要从STUN端口发送?
orm
STUN服务器给客户端A分配的relay地址都具备必定的有效时长,多是30秒或者1分钟或者几十分钟。客户端若是须要STUN服务器一直为它开启这个端口,就须要定时的向STUN服务器发送请求,该请求用刷新relay端口的剩余时间。
在标准的TURN(RFC 5766)协议中,客户端A向STUN服务器发送Allocate请求,STUN服务器在响应消息中添加了一个“LifeTime”的属性,该属性表示relay的存活时间。 客户端须要在relay的存活时间内周期性的调用REFRESH请求,服务端接收到REFRESH请求后,刷新剩余时间;当REFRESH请求中的lifetime属性为0时,说明是客户端主动要求关闭relay地址。io
因为与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发送。form
如上图所示是B主动给A发消息:“Hello”,A回应“Hi”的过程。
序号一、二、三、四、5为B的发送请求(蓝色箭头方向);
序号六、七、八、九、10为A的回应,原路返回(绿色箭头方向)。
注意:在“Hello”发送的过程当中,一、2阶段时,发送的数据为裸的UDP数据。在四、5过程当中,是被STUN协议包装过的“Hello”,称之为Data indication。
一样在“Hi”发送的过程当中,六、7阶段为被STUN协议包装过的“Hi”,称之为Send indication,九、10是裸的UDP数据。
在四、5阶段,因为数据是从STUN Port转发下来的,为了可以让客户端A知道这个包是哪一个客户端发来的,因此,STUN 协议对“Hello”进行了从新的包装,最主要的就是添加了一个XOR-PEER-ADDRESS属性,由裸数据包装成STUN协议的过程,咱们称之为添加了STUN头。XOR-PEER-ADDRESS的内容就是客户端B的反射地址(Server Reflexive Address)。
在六、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端口发出的过程。class
客户端B主动发送信息给A的交互流程如上图所示,那么客户端A主动发送信息给客户端B的交互流程是怎样的呢,你能画出来吗?
要知道客户端A主动发消息给客户端B,应该将消息发往客户端B的relay port哦。。原理