我有一个python服务器侦听udp数据包并回复发送者。在客户端中,我在同一端口创建连接回服务器。客户端在gsm网络上工作,他们的ip不是公共的,所以网络完成了一些端口映射,所以服务器可以联系回来,我想。
有时候端口映射必然会遇到一些问题,因为打开的套接字仍然可以与客户端 - >服务器通信,但不能反过来。
我有两个客户端使用相同的对(ip,地址)。在服务器中,当我使用 sock.recvfrom 接收来自他们的消息时,我清楚地知道消息是来自两个不同的客户端,考虑到他们的内容,但地址是相同的。
我在服务器上放了一个 nc -l </ strong>,并在每个客户端上运行 nc ,并清楚两个gsm卡共享相同的外部IP,所以最后一个打开端口,得到它的映射,旧的映射正在工作,假设它仍然有映射(不再有它)。
我没有制作我正在使用的原始代码,所以我无法解释为什么特定的给定端口用于接触服务器的客户端,但在我看来,即使使用随机端口,问题仍然存在持续存在是因为网络在一段时间后重新映射端口(我想它应该在像gsm信号丢失之类的某些事件之后)。
任何人都知道如何避免这种情况?
答案 0 :(得分:2)
在动态NAT中,内部端必须启动连接,NAT设备正在从内部数据包的5元组中分配状态:
{protocol, internal_ip, internal_port, foreign_ip, foreign_port}
构建一个状态条目(假设只有一个外部IP)必须使用5元组中剩余的 4 匹配较少区别的外部流量:
{protocol, _, internal_port, foreign_ip, foreign_port}
查看外部4元组和您的协议/配置,您可能会发现在没有冲突的情况下,每个外部NAT设备上的此服务永远不会有多个状态条目。
此外,由于UDP没有握手,因此来自客户端的每个新数据包都可以同等地启动新状态。因此,您所描述的问题实际上源于冲突的现有状态,而不是缺乏状态,因为TCP连接在动态NAT条目之后仍然处于空闲状态。
NAT设备是否区分外部流量的元组的所有4个可能部分以及状态条目持续多长时间的细节通常是可配置的。它如何处理重叠状态可能会有所不同(最近创建,最近使用,阻止新的冲突状态),但通常是不可配置的。尽管如此,假设一组不同的NAT设备(即没有一个主导的电信公司只有一个配置),如果你确保至少有多个非冲突的外部 4元组>,你将获得良好的平均结果在配置良好的NAT设备后面为您的客户提供。
如果客户端使用DNS获取服务器,则可以使用尽可能多的IP进行循环。每次将服务器在IP元组中的IP加倍时,每个NAT设备上的非冲突状态就会增加一倍。
在每次机会中,您可以更改一半客户端以发送到不同的服务器端口或选择不同的客户端端口,您也会将非冲突状态的数量相乘,除非在非常配置的NAT设备中。由于端口不足,这比获取IP块(或区域块)要实用得多。
最后一种可能性是增加应用程序级协议的复杂性。例如,让服务器仅在默认端口上发送新端口#。我会小心你不会慢慢重新实现STUN等现有服务。
如果客户端的设置端口与服务器不同,那么某些前任可能会遇到重大过滤(只要有动态NAT,就会有状态过滤的所有先决条件,所以没有过滤的NAT是罕见的。)在这种情况下,最好不要使用随机端口,但可能是地址空间中相当高的一千块左右。如果客户端具有与服务器相同的端口,那么前任在选择匹配&#34;的端口时可能会感到困惑或懒惰。从随机的高端口绑定开始以最小化冲突可能会很好,然后让客户端在无法连接的情况下回退到最佳测试。在任何一种情况下,您都必须寻找固定客户端端口所依赖的位置。
如果您的服务器支持多个客户端应用程序或客户端应用程序是线程,分支等,那么它们也可能是来自同一设备上不同上下文的两个sendmsgs。 UDP中的4元组不一定是独占的,因为它在TCP中,但您很可能对您的系统和协议有足够的了解,以排除这种可能性。
如果您的客户被直接分配了真实地址并在重新分配之后继续使用它们,我会说操作系统没有意识到,除了您的服务之外,这些客户端应该会出现很多问题,或操作系统知道,但已经做了一些不足之处,比如标记它们已弃用,但如果它们保持绑定端口,则可供客户访问。我对这一点持怀疑态度,因为它需要在客户的网络管理和电信网络中的工程设计中进行大量的过度工程,所以我认为少数客户会以这种方式出现还有其他更难描述由于流量丢失等造成的错误。我仍然会考虑:
get*
查找。