基于P2P技术实现内网到内网UDP穿透--转载
P2P:只要是数据量很大,而一般利用中转服务器又需要一定规模投入的应用,我们都可以考虑用P2P技术。
好处:
1.降低成本与投入。
2.提高传输性能。
一般情况下,我们做网络程序,首先都会考虑用TCP的方式来实现,用TCP的方式主要的好处有:
1.编写程序简单,大部分是采用C-S模型,也就是客户端对服务器。
2.TCP的特性保证了数据传输的可靠性,只要适当定制好协议,基本不会有网络丢包与边界的问题。
但同时,TCP也有缺点,就是通信效率较低。
做好P2P应用至少需要解决两个问题:
1.实现内网之间机器的网络通信。
2.需要解决UDP出现的数据传输不稳定问题。
内网穿透
假设一台在NAT211.133.*后的192.168.1.77:8000要向NAT211.134.*后的192.168.1.88:9000发送数据,假设你向211.134.*这个IP地址的9000端口直接发送数据包,则数据包在到达NAT211.134.*之后,会被当做无效非法的数据包被丢弃,NAT在此时相当于一个防火墙,会对没有建立起有效SESSION的数据包进行拒绝转递。当然,你也不能直接用内网地址192.168.1.88进行发送数据包,这就好比你在广州要打电话到上海的某个地方,如果你不加区号,直接拨打区域内电话是件很愚蠢的事。
首先我们要认识NAT设备,NAT英文全拼是Network Address Translator(网络地址转换器),说白了就是凡是经过NAT发出去的数据包,都会通过一定的端口转换(而非使用原端口)再发出去,也就是说内网和外网之间的通信不是直接由内网机器与外网NAT进行,而是利用内网对外网的NAT建立起SESSION与外网NAT的SESSION进行。
根据SESSION的不同,NAT主要分成两种:SymmetricNAPT以及CONE NAPT。简单的说,Symmetric NAPT是属于动态端口映射的NAT,而CONE NAPT是属于静态端口映射的NAT。而市场上目前大多属于后者,CONE的英文意思锥,意思就是一个端口可以对外部多台NAT设备通信。这个也正是我们做点对点穿透的基本,是我们所希望的,否则现在的大部分点对点软件将无法正常使用。
像上面的例子,NAT211.133.*和NAT211.134.*之间需要进行通信,但开始不能直接就发数据包,我们需要一个中间人,这个就是外部索引服务器(我们假设是211.135.*:7000),
- NAT211.133.*向211.135.*:7000发送数据包,211.135.*:7000是可以正常接收到数据,因为它是属于对外型开放的服务端口。
- 211.135.*:7000收到数据包后可以获知NAT211.133.*对外通信的临时SESSION信息(这个临时的端口,假设是6000会过期,具体的时间不同,但我个人的测试是每30秒发送一个心跳包keep住连接以保证端口维持住通信连接不断开),索引服务器此时应将此信息保存起来。
- 同时,NAT211.134.*也在时刻向索引服务器发送心跳包,索引服务器就向NAT211.134.*发送一个通知,让它向NAT211.133.*:6000发送探测包(这个数据包最好多发几个),
- NAT211.133.*(跟人觉得这里应该是NAT211.134)在收到通知包之后再向索引服务器发送反馈包,说明自己已经向NAT211.133.*:6000发送了探测包,
- 索引服务器在接收到反馈包之后再向NAT211.133.*转发反馈包,
- NAT211.133.*在接收到数据包之后再向原本要请求的NAT211.134.*发送数据包,此时连接已经打通,实现穿透,NAT211.134.*会将信息转发给192.168.1.88的9000端口。
对于Symmetric NAPT的情况,网上有人说可以通过探测端口的方式,不过成功率并不高,我建议可用服务器进行中转。
另外,最好在数据包发送前先检测是否进行的是同个NAT的情况,也就是内网发内网,如果是,直接发送即可,而无需通过外网再绕回来。
其次关于第二点,解决UDP传输的不稳定问题,其实这里涉及到另一个方面的知识,就是滑动窗口的东西,
可以开一个缓冲区用于循环接收数据以及重组,另外加上超时重发机制以及确认发送机制,有点像TCP的传输原理,不过如果处理的好,效率绝对比采用TCP的方式要高。