当两个客户端都在NAT后面时如何创建P2P连接

时间:2013-08-29 19:51:36

标签: c# .net tcp

是否可以在两个位于不同NAT后面的客户端之间建立直接连接? 当然,我意识到在某种程度上,具有公共IP的服务器将是必不可少的,但我不希望它成为代理。请看下面的场景:

  • 我不想与配置网络设备有任何关系。我只是想用代码来做。
  • 我不希望服务器参与文件传输过程(出于性能原因)
  • 我们有:客户端A,客户端B和服务器S,它看起来有点像这样:
  

A - [路由器1] - S - [路由器2] - 乙

  • A连接到S并授权
  • B连接到S并授权
  • A想要将文件发送给B
  • A要求S连接到B
  • S [这里有魔力],A现在与B
  • 有联系
  • A开始发送文件
  • S关闭(或至少文件传输绕过)
  • A和B之间仍然存在联系
  • A继续将文件发送给B

我的问题:

  1. 可能吗?
  2. 怎么做?
  3. 遇到过可以执行此操作的示例项目吗?
  4. 我找到了WCF / WPF Chat Application,但结果证明它是代理人。

    我还发现了一些建议使用UPnP和NAT Traversal的帖子,但没有人直接回答我的第一个问题所以我没有深入研究它。

1 个答案:

答案 0 :(得分:5)

您正在寻找“神奇部分”的术语称为NAT Hole Punching。不幸的是,这个主题有点过于宽泛,无法在此完全解释如何完成它,但现在知道正确的术语至少应该能够让你开始寻找正确的教程。

以下是UDP Hole Punching页面中算法的摘要。

  

让A和B成为两个主机,每个主机都在自己的专用网络中; N1和   N2是两个具有全局可达IP地址P1和的NAT设备   分别为P2; S是一个全球知名的公共服务器   可达的IP地址。

     
      
  1. A和B各自与S开始UDP会话; NAT设备N1和N2创建UDP转换状态并分配临时外部   端口号X和Y
  2.   
  3. S检查UDP数据包以获取N1和N2使用的源端口(外部NAT端口X和Y)
  4.   
  5. S将P1:X传递给B,P2:Y传递给A
  6.   
  7. A向P2发送数据包:Y和B使用与S对话相同的源端口向P1:X发送数据包,从而“打孔”一个洞   NAT转向其他主机
  8.   
  9. 如果任一主机收到数据包,则打孔成功,两个主机都可以通信。
  10.         

    如果两个主机都有Restricted cone NATsSymmetric NATs,则外部NAT端口将与S使用的端口不同。   路由器,外部端口顺序选择使其成为可能   通过猜测附近的港口建立对话。

它是否能够正常工作在很大程度上取决于端点的NAT路由器的行为方式,很可能您的大部分用途都将配对,并且两者都有非“打孔友好”的路由器。

在您的情况下,我会让我的软件按顺序尝试这些步骤。

  1. 检查并查看我们是否可以直接连接(用户进行手动端口转发)
  2. 使用UPnP并打开端口
  3. 使用公共服务器进行某种形式的打孔
  4. 使用另一个打开端口的对等方作为数据的代理(Supernode)。
  5. 使用我作为代理托管的服务器转发数据。