真实面经题目 · 原创解析

TCP如何识别断开?

TCP 识别断开依赖报文、应用读写行为和超时机制共同完成。正常关闭通常通过 FIN 体现,应用读到 0;异常关闭常见为 RST,读写报错;静默断链不会立刻被发现,需要 keepalive、应用层心跳和业务超时兜底。

出现于:阿里巴巴 · 客户端

60 秒回答模板

可以分三类回答。第一类是正常关闭:对端调用 close 或 shutdown 后发送 FIN,本端内核收到 FIN 后进入对应关闭状态,应用层继续读 socket,如果缓冲区已经读完,会读到 0,表示对端发送方向关闭。第二类是异常关闭:对端进程崩溃、端口无对应连接、强制关闭或向已不存在的连接发数据,都可能产生 RST,本端在 read 或 write 时得到 ECONNRESET;继续向已关闭读端写入还可能出现 EPIPE 或 SIGPIPE。第三类是静默失效:拔网线、机器断电、移动网络切换、NAT 映射消失、防火墙丢弃空闲连接时,双方可能收不到 FIN 或 RST,连接在本地仍显示存在,只有后续发数据、重传失败、TCP keepalive 失败、应用层心跳超时或业务超时后才会发现。工程上不能只等系统通知,长连接一般会组合 read 返回 0、读写错误码、连接超时、读写超时、idle 超时、TCP keepalive 和应用层 ping/pong。排查时要对齐客户端、服务端和中间设备时间,看日志错误码、TCP 状态、抓包中的 FIN、RST、重传和 keepalive 探测。

考点 正常关闭
主线 异常重置
易错点 认为 TCP 连接断开一定会立刻通知应用,忽略静默半开…

深入解析

01

正常关闭

正常关闭通常表现为 FIN。对端发送 FIN 代表它不再发送数据,但 TCP 支持半关闭,本端仍可能继续发送。应用层在接收缓冲区数据读完后 read 返回 0,这个 0 是 EOF,不是错误,也不是超时。

02

异常重置

RST 表示连接被重置,常见于对端异常退出、端口没有对应连接、应用强制关闭或协议状态不一致。本端读写时可能得到 ECONNRESET,说明原会话已经不可继续使用,需要关闭连接并按业务策略重连。

03

写侧发现

write 成功不等于对端应用已经收到,只代表数据进入了本机发送缓冲区或被内核接收处理。若对端已经重置,后续 write 可能返回 ECONNRESET;若继续向关闭的读端写,类 Unix 系统可能返回 EPIPE 并触发 SIGPIPE。

04

半开连接

静默断链最难处理。断电、拔网线、移动网络切换、NAT 映射过期时,不一定有 FIN 或 RST 到达另一端,因此本地连接可能仍处于 ESTABLISHED。没有数据交互时,内核可能很久都不知道连接已经不可用。

05

探测与超时

TCP keepalive 是内核级空闲探测,适合清理半开连接,但默认周期通常很长。应用层心跳更可控,可以用较短 ping/pong 周期判断对端应用是否仍可处理请求。业务还要设置连接、读写、请求和空闲超时。

06

排查方式

排查要先判断是 FIN、RST 还是超时。FIN 偏正常生命周期,RST 偏异常重置,超时偏链路或中间设备静默丢弃。再结合客户端日志、服务端日志、socket 错误码、TCP 状态和抓包,定位真正断开点。

易错点

  • 认为 TCP 连接断开一定会立刻通知应用,忽略静默半开连接。
  • 把 read 返回 0 当成异常错误,而不是正常 EOF 或半关闭信号。
  • 认为 write 成功就等于对端应用已经收到并处理数据。
  • 只依赖 TCP keepalive,不设置应用层心跳和业务超时。
  • 排查时只看服务端日志,不对照客户端、中间设备和抓包结果。

面试官追问

read 返回 0 和返回 -1 有什么区别?

read 返回 0 通常是对端正常关闭发送方向,属于 EOF;返回 -1 表示发生错误,需要看 errno,常见有 ECONNRESET、ETIMEDOUT、EAGAIN 等。

拔网线后为什么服务端不马上知道?

拔网线不会自动产生 FIN 或 RST,服务端没有收到任何控制报文,本地状态仍可能是 ESTABLISHED。只有发包重传失败、keepalive 失败或心跳超时后才会发现。

TCP keepalive 和应用心跳有什么区别?

TCP keepalive 由内核维护,判断连接路径大致是否可达;应用心跳由业务协议维护,能判断对端应用是否还活着、是否还能处理请求,周期也更容易按业务调整。

服务端如何清理长连接死连接?

通常结合空闲超时、读写超时、TCP keepalive、应用层心跳、连接池生命周期管理和错误码处理。只等待客户端主动 close,在公网和移动网络场景下不可靠。