比如通讯双方都在NAT后面,协调打洞的服务器在公网里!服务器告诉A端打洞(IP,Port),于是A就往那里发UDP报文,这时候报文在经过NAT的时候会有转换(内网IP转换成外网IP,内部端口会转换成路由端口,然后把这些转换记录进路由表里)数据就发出去了,这样A端NAT就有个洞了!
但是服务器再告诉B端坐同样的事的时候B肯定是要往A端的路由端口发送的吧?那么哪呢他是怎么知道A端路由口是多少的?

解决方案 »

  1.   

    因为A端首先进行打洞,B端NAT肯定会过滤掉这阵数据,B端主机是收不到数据的,所以B端打洞往哪里发呢?
      

  2.   

    NAT打洞,需要知道NAT的类型。
    最简单的一种打洞方式: A,B在各自的NAT后面, S端在公网。
    1、A,B各自跟S端建立UDP连接, 此时S端就有了A、B端的外网IP地址和端口号:AIP,APOP,BIP,BPOP.并把这些数据发生给对方。
    2、A-》B发送一个数据,并同时向S端发送打洞请求(也就一个自定义数据包)。
    3、S端收到A的打洞请求后,S端发送一个数据给B,通知B,A请求打洞。
    4、B接收到S端的数据,B端就想A端发送数据,因为前面A已经想B的外IP和端口号发送数据了,所以B向A发送的数据A是能够接收到的。
    5、A接收到B的数据后,再返回一个数据个B 这样一个P2P连接就连接好了。
    6、5分钟一次各自向对方发送数据,来维护这个连接。
      

  3.   

    当A向B打洞时往B端发数据的目的端口是B与S通信使用的端口吗?
      

  4.   

    当A向B发打洞报文时, A发送给B报文的接收端口是 B与S通信使用的外部端口吗?
      

  5.   

    A,B登录S端,A,B的外网IP和端口后都在S端了。
    A向B发送数据,是想B的外网IP和端口号发送数据。都是外网IP和外端口号。
      

  6.   

    可能说的不够明白,AB与S通信后  S知道了他们的外部IP与Port   然后S再把AB对方的这些信息告诉他们, A向B打洞的时候路由会打开一个新端口发送吧?   那么B端打洞发数据他知道新打开的端口是什么吗?  B端发到A与S通信的端口A的路由会帮B转换吗?
      

  7.   

    A想B发送数据时,会不会有个新的端口号,这是看NAT类型。Symmetric NAT它会对每一个外网节点发送数据时重新分配一个端口号。如果两边都是Symmetric NAT 基本上是实现不了P2P打洞的
      

  8.   

    哦,我明白了!原来打洞是建立在这个基础之上的!就是NAT后的主机无论发送给外网哪个节点的,路由转换的端口是固定的,不会重新分配了啊;这个主机和外网好多节点通信是使用的一个路由的端口出去的
    所以才B端才能知道往哪发啊????
      

  9.   

    1、 S启动两个网络侦听,一个叫【主连接】侦听,一个叫【协助打洞】的侦听。  
    2、 A和B分别与S的【主连接】保持联系。  
    3、 当A需要和B建立直接的TCP连接时,首先连接S的【协助打洞】端口,并发送协助连接申请。同时在该端口号上启动侦听。注意由于要在相同的网络终端上绑定到不同的套接字上,所以必须为这些套接字设置 SO_REUSEADDR 属性(即允许重用),否则侦听会失败。
      4、 S的【协助打洞】连接收到A的申请后通过【主连接】通知B,并将A经过NAT-A转换后的公网IP地址和端口等信息告诉B。  
    5、 B收到S的连接通知后首先与S的【协助打洞】端口连接,随便发送一些数据后立即断开,这样做的目的是让S能知道B经过NAT-B转换后的公网IP和端口号。  
    6、 B尝试与A的经过NAT-A转换后的公网IP地址和端口进行connect,根据不同的路由器会有不同的结果,有些路由器在这个操作就能建立连接,大多数路由器对于不请自到的SYN请求包直接丢弃而导致connect失败,但NAT-A会纪录此次连接的源地址和端口号,为接下来真正的连接做好了准备,这就是所谓的打洞,即B向A打了一个洞,下次A就能直接连接到B刚才使用的端口号了。
      7、 客户端B打洞的同时在相同的端口上启动侦听。B在一切准备就绪以后通过与S的【主连接】回复消息“我已经准备好”,S在收到以后将B经过NAT-B转换后的公网IP和端口号告诉给A。
      8、 A收到S回复的B的公网IP和端口号等信息以后,开始连接到B公网IP和端口号,由于在步骤6中B曾经尝试连接过A的公网IP地址和端口,NAT-A纪录了此次连接的信息,所以当A主动连接B时,NAT-B会认为是合法的SYN数据,并允许通过,从而直接的TCP连接建立起来了。