Android 上的 Indy10。如何强制 TIdUDPClient 尊重 BoundPort 属性 进行 GSM 网络连接?

Indy10 on Android. How can I force TIdUDPClient to respects BoundPort Property for GSM network connection?

在 C++Builder Android 项目中,当设备连接到 WiFi 网络时,TDataModule 上的 TIdUDPClient 按照预期尊重其 BoundPort

// BoundPort property is set to 55555...

amcDeviceDM->UDPC->Active = true;
amcDeviceDM->UDPC->Connect();
if(amcDeviceDM->UDPC->Connected())
{
    amcDeviceDM->UDPC->SendBuffer(fHost,fPort,Id_IPv4,DataPkt);
}

从 UDP 服务器接收日志中提取:

PeerPort = 55555

如果 WiFi 被禁用,而是设备连接到 GSM 网络(如 Telstra Australia),BoundPort 属性 将被忽略,并且 UDP 服务器接收日志显示:

PeerPort = 37091

如果WiFi重新激活,服务器再次显示:

PeerPort = 55555

有谁知道如何确保始终选择正确的发送端口,即使网络套接字发生变化也是如此?

Indy 没有 WiFi 与 GSM 网络的概念。它只是将套接字绑定到本地 IP/port,而不管它们恰好在 OS/hardware 层关联到什么。您没有看到任何异常引发的事实意味着绑定成功(并且您可以通过在激活套接字后查看 amcDeviceDM->UDPC->Binding->Port 属性 来验证)。

当连接到 GSM 网络时,设备没有 直接 连接到互联网。提供商充当 gateway/proxy 为设备提供互联网访问权限。因此,UDP 服务器将从属于提供商系统的 PeerIP/PeerPort 对接收数据包,而不是设备(如果 UDP 服务器正在记录PeerIP)。无论 BoundPort 您决定将 TIdUDPClient 绑定到您设备上的本地,都 对提供商系统使用的端口绑定没有任何影响 ,并且您无法控制那。这很好,因为提供商会为您处理设备 IP/Port 和提供商 IP/Port 之间的链接,因此可以根据需要在它们之间路由数据包。

当连接到 WiFi 时,设备仍然没有直接 连接到互联网。路由器充当网关,为设备提供互联网访问权限。因此,UDP 服务器将从属于路由器而非设备的 PeerIP/PeerPort 对接收数据包。无论 BoundPort 您决定将 TIdUDPClient 绑定到本地 可能会或可能不会 由路由器保留。当路由器看到需要转发到网络 public(Internet)端的传出 UDP 数据包时,路由器将打开绑定到路由器 public IP 的端口(如果尚未打开),然后从 public IP/Port 发送数据包。 public IP/port 接收到的任何 UDP 数据包将被转发到设备的 IP/Port。打开的端口号通常通常 与原始数据包使用的端口号相同,前提是该端口号当前在路由器上可用,但这并不能保证。因此,即使在 WiFi 网络上,UDP 服务器仍然有可能看到与设备绑定的内容不同的 PeerPort。这很好,因为路由器将为您处理设备 IP/Port 和路由器 IP/Port 之间的链接,因此可以根据需要在它们之间路由数据包。如果您需要保证路由器的public端口号,您必须在设备开始发送数据包之前在路由器上配置端口映射规则,或者在路由器的静态配置中, 或动态地通过 uPNP.