利用P2P点对点技术实现UDP内网穿透

 介绍之前首先推荐一个程序员专用搜索引擎-http://www.openso.net

  从上面的描述,我们可以得出两个结论,做好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主要分成两种:Symmetric NAPT以及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.133.*:6000发送了探测包,索引服务器在接收到反馈包之后再向NAT211.133.*转发反馈包,NAT211.133.*在接收到数据包之后再向原本要请求的NAT211.134.*发送数据包,此时连接已经打通,实现穿透,NAT211.134.*会将信息转发给192.168.1.88的9000端口。
  对于Symmetric NAPT的情况,网上有人说可以通过探测端口的方式,不过成功率并不高,我建议可用服务器进行中转。另外,最好在数据包发送前先检测是否进行的是同个NAT的情况,也就是内网发内网,如果是,直接发送即可,而无需通过外网再绕回来。
  其次关于第二点,解决UDP传输的不稳定问题,其实这里涉及到另一个方面的知识,就是滑动窗口的东西,可以开一个缓冲区用于循环接收数据以及重组,另外加上超时重发机制以及确认发送机制,有点像TCP的传输原理,不过如果处理的好,效率绝对比采用TCP的方式要高。另外对于滑动窗口机制的知识在这里就不说了,有兴趣可以上网找找资料。

 

相关内容推荐