在tcpdump抓包同一个tcp.stream index中存在fin->rst
tcp.stream eq 13520完美锁定了这一条流。总结为:客户端本想优雅地关闭连接(FIN),但服务端却无情地直接掀了桌子(RST)。
1. 正常的前半段:HTTP 业务顺利完成
- POST 请求:客户端(
100.127.128.146)向服务端(192.168.3.4)发送了一个POST /ocr_v4_mobile请求,传输的是 JSON 数据。 - 200 OK 响应:服务端很给力,立刻返回了
HTTP/1.1 200 OK,也带有 JSON 回应。 - 到这里为止,业务层面的交互已经圆满结束了。
2. 转折点:蓝色包的 [FIN, ACK]
- 动作:服务端(
192.168.3.4)主动向客户端发送了一个[FIN, ACK]。 - 含义:服务端在说:“我的数据已经发完了,我想关闭这个连接。”
按照标准的 TCP 四次挥手流程,客户端收到 FIN 后,应该回应一个 ACK,然后客户端自己也发一个 FIN,连接才算优雅地完全关闭。
3. 为什么后面会出现大面积红色 [RST]
紧接着蓝色包之后,现场立刻“血流成河”(大面积红色报错包)。
服务端(192.168.3.4)疯狂向客户端发送 [RST](Reset)信号,意思是:“别发了!这个连接在我这里已经彻底销毁了,拒绝沟通!”
之所以会这样,是因为客户端在收到 FIN 后,依然在盲目地往服务器发送数据(看那些夹在红色中间的淡蓝色/白色 ACK 包,长度 1446,说明客户端还在疯狂传数据,或者重传之前没被确认的数据)。
通常由以下几种原因导致:
原因一:客户端应用层没有理会服务端的关闭信号(最常见)
服务端的底层网络栈已经发送了FIN表示要收工,但是客户端的业务程序可能根本没意识到服务端要关闭,或者它手里还有一堆数据(比如未传完的图片、日志)没发完,继续硬塞给服务端。原因二:服务端已经关闭了Socket 缓冲区
服务端发送FIN后,如果其应用层立刻关闭了该 Socket(调用了close()而非shutdown(SHUT_WR)),此时它的接收缓冲区会被直接清空并关闭。此时客户端要是再敢发一丁点数据过来,服务端的底层网络栈就会直接触发RST报错。原因三:客户端的 ACK 迟到了或者在重传旧数据
注意看那些 1446 字节的包,它们可能是在蓝色FIN包发出之前,就已经在网络管道里飞向服务器了(网络延迟导致的乱序)。服务器既然已经决定关门(发送了 FIN 甚至关闭了 socket),这时候撞上门来的任何数据包都会被视作“非法”,直接用RST顶回去。
总结
简单来说,**FIN -> RST 表明这是一个“非优雅”的连接终止**。
这通常是应用层代码逻辑没设计好导致的(比如没有处理好 TCP 的半关闭状态,或者服务端急着 close 释放资源,没给客户端留足够的收尾时间)。