2

我有一个奇怪的问题。我有一个成功运行的 C++ (boost asio) P2P 应用程序,它可以在大多数 NAT 上运行。问题是当我将初始起始端口号设为 1000 时,它会检查 1000 是否空闲,否则会加一并选择一个端口并开始握手。但是当我有 10000、20000 或任何其他巨大的端口号时,打孔在端口受限的锥形 NAT 上不起作用。

这怎么可能?我很确定这与代码无关。最近它也不适用于我朋友的一个全锥 NAT,但它已在许多其他全锥 NAT 中工作。可能是什么原因?关于 NAT 的行为,我有什么遗漏吗?

4

3 回答 3

3
  1. 在许多 NAT 实现中,有一些保护规则可以防止一台主机占用 WAN 接口上的大部分端口,例如此处所述。

  2. 根据路由器的不同,NAT 表条目具有不同的生命周期,并且对于可以分配给单个客户端的端口数量总是有限制的(我见过从 128 到 4096 的数字)。

因此,我认为当您需要使用高端口时,您的源 IP 地址的 NAT 表已经满(或几乎满)来自旧连接的条目或来自其他应用程序的连接,因此路由器要么决定拒绝或不适合您的端口的新 NAT 条目。

但是,可以肯定的是,我会尝试在受控环境中重复这一点,收集 NAT 两侧的 Wireshark 转储并分析数据包。如果可能的话,启用路由器日志并查看它们也会有所帮助。

我知道这不是“灵丹妙药”,但希望它对您有所帮助。

于 2013-04-14T22:42:14.020 回答
3

不要试图自己选择端口号。操作系统可以比您的代码更快更好地做到这一点。

将您的套接字绑定到端口 0 并让操作系统为您选择一个可用的端口号。您没有指定什么编程语言,但它通常涉及在调用 bind() 后调用getsockname () 以发现将使用的本地端口。Java 和 .NET 具有用于执行相同操作的等效 API。

然后按照此处的所有其他步骤操作: https ://stackoverflow.com/a/8524609/104458

于 2013-04-15T03:11:02.473 回答
0

Not sure if this'll help but have you tried having one instance of the client application starting at 1001 and the other starting at 1000, then both increment by 1.

While the 1000 will fail on client B, client A has already tried 1001 and so punched that hole, so hopefully it'll work, right? In theory, it sounds OK in my head.

于 2014-06-13T15:40:10.583 回答