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