4

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

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

A--[Router1]--S--[Router2]--B

  • A连接S并授权
  • B连接S并授权
  • A想向B发送文件
  • A 向 S 请求与 B 的连接
  • S [这里有魔法吗] 现在 A 与 B 有联系
  • A开始发送文件
  • S 下降(或至少文件传输绕过是)
  • A和B之间仍然存在联系
  • A继续向B发送文件

我的问题:

  1. 那可能吗?
  2. 这个怎么做?
  3. 有没有遇到可以做到这一点的示例项目?

我找到了WCF / WPF Chat Application,但结果证明它是一个代理。

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

4

1 回答 1

7

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

这是来自UDP Hole Punching页面的算法摘要。

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

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

如果两台主机都有Restricted cone NATsSymmetric NATs,则外部 NAT 端口将与 S 使用的端口不同。在某些路由器上,外部端口是按顺序选择的,因此可以通过猜测附近的端口来建立对话。

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

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

  1. 检查我们是否可以连接(用户进行了手动端口转发)
  2. 使用 UPnP 并打开一个端口
  3. 使用某种形式的打孔,使用公共服务器作为两者之间的过渡
  4. 使用另一个打开了端口的对等点作为数据的代理(超级节点)。
  5. 使用我托管的服务器作为代理来转发数据。
于 2013-08-29T19:54:37.257 回答