Delphi 10.4.2升级后Android端TDSRestConnection移动网络异常求解
Delphi 10.4.2升级后Android端移动网络REST连接异常修复指南
异常表现:APP仅在WiFi网络下可正常交互,4G移动网络下长SQL请求会触发连接超时、连接重置错误,错误触发位置不固定,切换不同运营商网络无改善;相同设备、相同网络下Delphi 10.1版本编译的APP可正常运行。
核心诱因定位
Delphi 10.4.2版本针对Android平台的REST组件网络栈做了底层调整,从10.1版本默认使用的Indy跨平台网络栈,替换为基于Android系统原生Java网络栈的NetHTTPClient实现,两类网络栈在移动网络NAT环境下的行为差异,是版本升级后问题复现的根本原因。
可落地的修复步骤
- 修正长参数的请求传递方式
当前代码中硬编码将GetSql接口的请求类型设为GET,长SQL语句直接作为URL参数传递。移动网络运营商的4G网关普遍对GET请求的URL长度做了1KB-2KB的截断限制,长度超标的请求包会被网关直接丢弃,表现为连接超时、连接重置;WiFi网络无此类截断规则,因此可正常运行。
修复方式:将长参数请求从GET调整为POST,把SQL参数放入请求Body传递,避开URL长度限制。代码改动点:
DSRest框架会自动将参数序列化到请求Body,无需额外处理参数读取逻辑。// 修改前 FGetSqlCommand.RequestType := 'GET'; // 修改后 FGetSqlCommand.RequestType := 'POST'; - 关闭默认的HTTP长连接复用机制
10.4.2版本默认启用NetHTTPClient的Keep-Alive连接复用优化,但移动网络运营商的NAT网关对空闲连接的回收时间普遍为30s-60s。当连续多次调用接口时,底层复用的连接可能已被网关静默回收,此时APP继续向旧连接发送数据就会触发Connection reset错误。
修复方式:在每个请求发起前强制添加请求头,要求单次请求完成后直接关闭连接,不做复用:DSRestConnection1.HTTP.CustomHeaders['Connection'] := 'close'; - 调整超时配置以匹配Android系统限制
当前代码设置的300000ms(5分钟)超时值,在Android 10以上系统中会被强制生效范围限制:Android系统对应用的网络连接超时最大值限制为30s,超过阈值的配置无法被系统正确识别,反而会因为内部逻辑不匹配,导致请求发起7-8s就提前抛出超时错误。
修复方式:将超时值调整为符合系统约束的范围:const fConnectTimeout = 30000; // 30s连接超时 const fReadTimeout = 60000; // 60s读取超时 - 适配Android 10以上的明文流量规则
10.4.2版本的Android编译目标默认禁用非加密HTTP的明文流量传输,部分运营商会对4G网络下的非加密HTTP请求做QoS优先级降权,导致大请求包被随机丢弃。可在项目的网络安全配置中,仅针对自身服务端地址开放明文流量权限,无需全局关闭加密校验规则。
辅助验证方法
- 对比10.1和10.4.2版本APP在同一设备、同一4G网络下的请求抓包结果,重点确认长请求是否被网关截断、是否存在空闲连接被静默回收的问题。
- 临时将DSRestConnection的底层HTTP实现切换回Indy网络栈,若切换后移动网络下请求正常,即可确认是原生网络栈的行为差异导致的兼容性问题。
内容的提问来源于stack exchange,提问作者Gianluca Colombo
相关产品推荐
相关产品推荐

