我有一个奇怪的问题。我有一个成功运行的C ++(boost asio)P2P应用程序,它适用于大多数NAT。问题是当我将初始启动端口号设置为1000时,它检查1000是否可用,否则增加1并选择一个端口并开始握手。但是当我有10000,20000或任何其他巨大的端口号时,打孔对端口限制锥形NAT不起作用。
怎么可能?我很确定它与代码无关。最近它也不适用于我朋友的全锥形NAT,但它在许多其他全锥形NAT中都有效。可能是什么原因?我是否遗漏了NAT的行为方式?
答案 0 :(得分:3)
在许多NAT实施中,存在保护规则,其防止一个主机占用WAN接口上的大部分端口,例如,如描述here。
根据路由器的不同,NAT表条目的生命周期不同,并且总是可以为单个客户端分配多少端口(我看过128到4096之间的数字)。
所以我认为当你到达需要使用高端口的程度时,源IP地址的NAT表已经满(或几乎已满),包含来自旧连接的条目或来自其他应用程序的连接,因此路由器决定拒绝或不适合您的端口的新NAT条目。
但是,可以肯定的是,我会尝试在受控环境中重复这一点,收集NAT两侧的Wireshark转储并分析数据包。如果可能的话,启用路由器日志并查看它们也会很有帮助。
我知道这不是一个“神奇的子弹”,但希望它能以某种方式帮助你。
答案 1 :(得分:3)
请勿尝试自行选择端口号。操作系统可以比代码更快更好地完成此任务。
将套接字绑定到端口0,让操作系统为您选择可用的端口号。您没有指定什么编程语言,但它通常涉及在调用bind()之后调用getsockname()以发现将使用的本地端口。 Java和.NET具有相同的API来执行相同的操作。
然后按照此处的所有其他步骤操作: https://stackoverflow.com/a/8524609/104458
答案 2 :(得分:0)
不确定这是否有帮助,但您是否尝试过一个客户端应用程序实例从1001开始,另一个实例从1000开始,然后两者都递增1.
虽然客户端B上的1000会失败,但是客户端A已经尝试了1001,因此打了那个洞,所以希望它能正常工作,对吗?从理论上讲,这听起来还不错。