1

我在 C/POSIX 中做一个 P2P 应用程序,我被 NAT 遍历困住了。

我阅读了多种方法(MiniUPnP、手动端口转发、TCP/UDP 打孔)和很多关于它的问题,但我发现了一些问题:

  • MiniUPnP : 看到transmission-cli用它来做端口转发,所以下载了MiniUPnP的源码,试着看懂了,但是太乱了,放弃了。我搜索了类似文档的东西来实现它(比如“这个函数需要那个结构来做一些事情并且会返回这个”)但没有找到任何有用的东西。(我认为这是最干净的方法,因为它只需要使用为此目的制作的库。如果有人知道如何使用该代码,请帮助我)
  • 手动端口转发:我希望用户不要弄乱他的路由器设置,所有工作都应该通过代码完成。
  • TCP 打孔:我读了这篇关于打孔的文章,我认为这是最简单的方法(我也有一个带有公共 IP 的 VPS,所以我可以像使用集合服务器一样使用它)但我无法连接不同 NAT 后面的两个不同用户。

设想

我有一个主服务器(在 VPS 上),它记录每个加入 p2p 网络的对等方,这就是发生的情况:

  1. PeerA 加入网络并向服务器发送这对夫妇(A_LOCAL_IP:A_LOCAL_PORT);
  2. 服务器保存了A的公网IP(XXXX)和公网端口(AAA)和A发来的这对夫妇。
  3. PeerB 加入网络并将服务器发送给服务器(B_LOCAL_IP:B_LOCAL_PORT)
  4. 服务器保存了 B 的公网 IP(YYYY)和他的公网端口(BBB)以及 B 发送的这对夫妇。
  5. PeerA 和 PeerB 都进入 for 循环等待 accept(),然后它们产生一个线程来处理传入的请求
  6. PeerA 想与 PeerB 连接
  7. PeerA 询问服务器,PeerB 的 IP:port
  8. 服务器向 PeerA 发送一对 (YYYY:BBB) 和 (B_LOCAL_IP:B_LOCAL_PORT) [这是最后一个,以防它们属于同一个 NAT]
  9. PeerA 生成一个线程,该线程进入 for 循环,尝试通过端口“BBB”连接或与“YYYY”连接,或通过端口“B_LOCAL_PORT”与“B_LOCAL_IP”连接,而“主线程”进入 for 循环尝试接受连接
  10. 服务器向 PeerB 发送两对 (XXXX:AAA 和 (A_LOCAL_IP:A_LOCAL_PORT)
  11. PeerB 产生一个线程,该线程进入 for 循环,尝试通过端口“AAA”连接或与“XXXX”连接,或通过端口“A_LOCAL_PORT”与“A_LOCAL_IP”连接,而“主线程”进入 for 循环尝试接受连接

这是交易:当我使用 (B_LOCAL_IP:B_LOCAL_PORT) 对时,它工作正常;当我使用 (YYYY:BBB) 对时,它不起作用。

在“ECONNREFUSED”的情况下,我使用指数回退,当我尝试使用 (YYYY:BBB) 对时,它会打印

拒绝连接。休眠 1 秒
连接被拒绝。睡眠 2 秒
连接被拒绝。睡眠 4 秒
连接被拒绝。睡眠 8 秒
连接被拒绝。休眠 16 秒
连接被拒绝。休眠 32 秒
最大超时已过期。中止...

当然,当另一个 NAT 下的某人试图加入我的 NAT 下的对等方时,也会发生这种情况。

所以就是这样,这些是我的问题:

  1. 为什么它使用 (B_LOCAL_IP:B_LOCAL_PORT) 对而不使用 (YYYY:BBB) 一对?
  2. 是否有可能我的 NAT 有一些配置/架构使得无法实现打孔?
4

0 回答 0