Api Demo | 接口原型

点对点通讯(P2P)原理及webRTC实现网页文件分享

2021-06-25T21:49:58
--------------------------------------------------------------------------------------------------------

技术细节 : 

前言

说明: 本文章为c4r小组所有, 采用CC BY-NC-SA 3.0协议. 且文章为小组成员调研和研究之后推理得到的结果, 可能存在片面性, 请读者自行判断. 欢迎讨论.

原理与流程介绍


主要参考 : 关于使用UDP(TCP)跨局域网,NAT穿透的心得

由于有限的IPV4地址, 使得无法做到每个上网的人都可以拥有固定并独立的IP地址. 这使得用户一般会先拿到一个路由器分配的局域网IP地址, 在访问外网的时候再分配一个公网(外网)IP地址. 假设现在有两个"人"想要相互之间传递数据, 我们称这两个人为A,B.


  1. 如果A, B在一个局域网

这种情况下, 两个人可以直接通过访问对方IP的方式直接传递数据

常见例子 : windos共享, 远程连接(ssh连接, 远程桌面)


2. 如果A在局域网, 而B拥有公告网IP

这种情况, A先访问B后, 建立连接后, 两者可以相互传递数据

常见例子 : 用户访问大型网站

具体过程 : 

假设 : A处于路由器(NAT)后面. 内网地址为192.168.0.2, 外网地址 168.38.1.2
B外网地址为 54.202.1.2

1) A首先像B发送数据(UDP包), 这时候A的路由器会记录下session, 
里面保存A内网IP和外网IP的对应/映射关系.
我们称A为了B在NAT上打了一个洞.

2) 这个时候当B要把消息发送给A的时候, NAT会自动把消息转发给A


3. 当A和B全部躲在路由器(NAT)后面

在连接A和B之前,需要通过一个服务器S告知A和B的外网IP
服务器S满足的协议是STUN
1) A和B分别连接服务器S. 
这样S就知道了A和B的公网IP. 
这个时候A:NAT会保存session:A-S, B:NAT保存session:B-S


2) 让A向B的公网IP发送数据. 
因为这个时候B:NAT不存在session:B-A 所以数据将会丢失. 
但是A:NAT会创建session:A-B.


3) 然后让B向A的公网IP发送消息. 
这个时候将会在B:NAT上建立session:B-A. 
这个时候A:NAT和B:NAT上都储存了对方的映射关系. 
现在A和B之间发送消息, 将会被NAT转发. 

过程如下图:


4. 当A或者B躲在NAT后面, NAT转发的端口会根据会话发生改变

比如A躲在一个NAT后面, 这个NAT具有如下特性:
每当A与外面连接, 对于不同的连接对象NAT会给A重新分配一个端口.
这种情况打洞非常困难, STUN服务器没办法办到, 需要使用TURN协议. 
TURN协议包括STUN协议.

TURN会给A或B分配一个临时的IP地址, 并且作为中继, 给A和B的数据进行转发. 
这种情况下, 数据会通过TURN服务器, 再发送给对方, 对TURN服务器带宽要求较高. 

据说这种情况比较少(参考). 单就个人实际使用情况发现, 这种情况还挺多的.

相关阅读 :

  1. STUN, TURN, ICE介绍

2. P2P通信标准协议之TURN


网页实现方案 : WebRTC


WebRTC技术让点对点通讯可以让用户通过浏览器建立点对点连接吗, 由谷歌提出. 目前Chrome和Firefox都支持该技术.

具体介绍参考MDN文档

使用教程

官方代码例子

搭建和使用WebRTC

主要需要:

  1. signalmaster

供WebRTC传递消息的服务器. 支持STUN/TURN协议, 默认STUN使用谷歌服务, TURN为空.

注意 : node 版本. 我测试的环境和结果:

1) Ubuntu:16.06LTS node : v4.2.6

signalmaster需要使用release:v0.2.2版本

2) CentOS release 7.3.1611 node : v6.14.2

signalmaster需要使用master分支最新版


2. SimpleWebRTC

| API查询 : github | demo |

对WebRTC的API进行了封装, 使用起来很容易.

不需要安装. 只需要在网页里加入

<script src="https://simplewebrtc.com/latest-v3.js"></script>

注意 : 

signalmaster v0.2.2 需要使用

<script src="https://simplewebrtc.com/latest.js"></script>


3. TURN服务器(可选)

完成1,2步之后, 网页就可以正常运行了. 但为了应对更复杂的情况需要使用TURN服务器.

因为singalmaster只支持the shared secret mechanism类型服务器, 我们选择coturn方案.

代码地址 : github主页

安装说明 : github wiki

注意 : 

在创建完成后, 需要在signalmaster里添加TURN地址和密码

     "turnservers": [
         {
      "url": "turn: coturn运行的IP地址/域名",
      "username":"创建coturn的用户名",
      "secret": "密码",
      "expiry": "86400"
         }
     ]


至此完成建设.