
问题:拔掉网线,TCP 连接还在不在?
我们在学习网络编程的时候,经常会用打电话来比喻双方的通信。那么 TCP 连接在拔掉网线的时候,是否和我们通电话一样,拔掉网线,通话就立即被终止了呢?
经过我的实际验证,结果总是出人意料的:在拔掉网线的时刻进行查看,原来的 TCP 连接还是处于 ESTABLISHED 状态。
那么这是为什么呢?
从宏观上说,网线属于物理层,而我们的 TCP 连接是属于传输层,物理层的改变不会直接影响到传输层。
从微观上说,TCP 连接在 Linux 内核中对应一个 struct sock 结构体(TCP 场景下就是 struct tcp_sock),这个结构体记录了 TCP 连接的状态,比如 ESTABLISHED。拔掉网线事件发生,操作系统维护的这个结构体没有发生任何变化。
这是因为 TCP 状态的改变依赖于协议层面的交互,而非物理链路的状态。只有当 TCP 协议栈通过超时、错误检测或其他机制确定连接不可用时,连接状态才会改变。
所以拔掉网线的那一刻,TCP 连接是还存在的,但是会一直存在吗?这就分两种情况了:
- 拔掉网线后,有数据传输
- 拔掉网线后,没有数据传输
拔掉网线后,有数据传输
客户端拔网线后,服务端发数据无响应,引发重传机制。
若客户端网线及时复位,服务端重传时段可顺畅接收并回以 ACK 响应,TCP 连接状态维持如初,通信似乎未受扰。
若客户端长时间未恢复,服务端重传超限时将认定连接故障,经 Socket 通知应用并断开连接。
客户端重连发送数据,因服务端端口无匹配连接,将以 RST 响应,客户端接收到后关闭连接,最终双侧 TCP 连接均告终。
拔掉网线后,没有数据传输
如果没有开启 TCP keepalive 机制,在客户端拔掉网线后,并且双方都没有进行数据传输,那么客户端和服务端的 TCP 连接将会一直保持存在。
而如果开启了 TCP keepalive 机制,在客户端拔掉网线后,即使双方都没有进行数据传输,在持续一段时间后,TCP 就会发送探测报文来确定对方的 TCP 连接是否存活。关于 keepalive 的详细机制,可以看本站的《TCPKeepalive》。
总结
简单地说,“拔掉网线后 TCP 连接是否还在”并不是一个绝对的是或否的问题。
在没有数据传输且短时间内恢复网络连接的情况下,TCP 连接可能看似不受影响;
在有数据交互或长时间断网的情况下,TCP 最终会检测到连接问题并采取相应的行动,导致连接断开。