Android HTTP持久连接遇[FIN/ACK]包:连接为何关闭?
关于HTTP持久连接中出现[FIN, ACK]包的问题分析
首先直接给结论:没错,[FIN, ACK]包确实表示对应的TCP连接正在被关闭——从你的Wireshark日志来看,是服务器端(10.92.33.190)主动发起了关闭请求,客户端回应了ACK确认。虽然你的请求和响应头都明确指定了Connection: keep-alive,但服务器实际并没有维持这个连接,这就是问题的核心所在。
结合你的技术栈(OkHttp 2.5.0 + Express服务器),我整理了几个可能的原因和排查方向:
1. 服务器端的Keep-Alive配置存在问题
你的响应头显示后端是Express(Node.js)服务,Node.js原生http模块虽然默认支持Keep-Alive,但如果配置不当会导致服务器主动切断连接:
keepAliveTimeout:默认值是5秒,表示连接在空闲状态下保持打开的时长。但从你的日志来看,服务器在响应后仅约0.6秒就发送了FIN包,这大概率是服务器端主动设置了更短的超时,或者有业务逻辑强制关闭了连接。headersTimeout:如果服务器在这个时间内没有收到客户端的下一个请求头,也会触发连接关闭。- 另外要排查是否有反向代理(比如Nginx)在中间干预了连接生命周期,或者Express的某个中间件在响应完成后主动触发了连接关闭操作。
2. 响应的Content-Length可能不匹配
你的响应头里指定了Content-Length: 558,但如果实际返回的JSON内容字节数和这个值不一致,服务器会认为响应传输出现异常,直接关闭连接。建议验证一下返回的JSON字符串的UTF-8编码字节数是否正好是558(注意是字节数,不是字符数)。
3. OkHttp客户端的连接复用逻辑(次要排查点)
虽然日志显示是服务器主动关闭连接,但也可以检查OkHttp的连接池配置:
- OkHttp 2.5.0默认的连接池最多保留5个空闲连接,空闲超时5分钟。如果你的客户端每次请求都创建新的
OkHttpClient实例,会导致连接无法被复用,但这不是你当前问题的主要原因,因为是服务器先发起了关闭。
排查建议
- 先调整Node.js服务器的配置,显式设置更长的Keep-Alive超时:
const server = http.createServer(app); // 设置连接空闲60秒后再关闭 server.keepAliveTimeout = 60000; // 请求头超时设置要比keepAliveTimeout稍长,避免冲突 server.headersTimeout = 61000; - 不要硬编码
Content-Length,在服务器端动态计算返回内容的字节数后再设置响应头:const jsonStr = JSON.stringify(yourData); res.setHeader('Content-Length', Buffer.byteLength(jsonStr, 'utf8')); res.end(jsonStr); - 查看服务器端的日志,排查是否有关于连接关闭的错误或警告信息,确认是否有中间件或业务逻辑触发了连接关闭。
内容的提问来源于stack exchange,提问作者SRam
相关产品推荐
相关产品推荐

