谈谈tcp的”藕断丝连“的那些事

序言:

  • 有这么一道题"如果A 与 B 建立了正常连接后,从未相互发过数据,这个时候 B 突然机器重启,问 A 此时处于 TCP 什么状态?如何消除服务器程序中的这个状态?",如果是你,你应该怎么去解答这道题,里面又包含了哪些知识点,那么今天,我就来当一次解题者,去彻底"剪断"这些丝线。

TCP连接过程和状态:

  • A与B建立tcp连接,需要经过三次握手过程,建立三次握手的过程就是老生常谈了,具体过程如下:

    1. SYN(同步序列编号) : 在连接建立的初步阶段,客户端发送一个SYN(synchronize)报文到服务器。在这个报文中,客户端会随机产生一个初始序列号(sequence number),告诉服务器它希望从这个数字开始传送数据。
    2. SYN-ACK(同步确认) : 当服务器收到客户端的SYN报文后,它需要确认客户端的SYN。服务器会向客户端发送一个SYN-ACK报文。在这个报文中,确认号(ACK number)是客户端的初始序列号加1,表示服务器已经接收到客户端的SYN,并期待从这个序列号开始接收数据。同时,服务器也会发送自己的初始序列号,准备开始另一个方向上的数据传输。
    3. ACK(确认) : 客户端收到服务器的SYN-ACK报文后,会发送一个ACK报文作为响应。这个ACK报文中的序列号是初始的ACK号,而确认号则是服务器的初始序列号加1。这表明客户端已经准备好接收服务器从这个序列号开始的数据。
    4. 通过这样的三步过程,TCP协议确保了双方都知道对方已经准备好进行数据传输,从而建立起了一个可靠的连接。这个连接将用于后续的所有数据传输活动。三次握手的过程不仅确保了连接的可靠性,还防止了序列号的重复使用和旧连接的幽灵连接现象,增强了通信的安全性。
  • 当A与B建立了正常的TCP连接后,即使它们之间从未相互发送过数据,TCP连接仍然被认为是处于"ESTABLISHED"(已建立)状态。这意味着双方都已完成了TCP三次握手过程,并且准备好进行数据交换。在整个TCP连接的生命周期中,会经历多个不同的状态。以下是TCP连接的主要状态及其简要说明:

    状态 描述
    CLOSED 表示没有任何连接是活动的或正在进行中,也就是说,端口是关闭的,不在监听。
    LISTEN 表示服务器端的某个SOCKET处于监听传入连接的状态。
    SYN_SENT 客户端已经发送一个连接请求(SYN包)给服务器,并等待回应。
    SYN_RECEIVED 服务器已收到客户端的SYN请求,并发送了一个SYN-ACK响应。等待客户端的ACK。
    ESTABLISHED 表示连接已被客户端和服务器双方确认,数据可以开始传输。
    FIN_WAIT_1 表示连接正在关闭中,等待对方的FIN报文或者对自己FIN报文的ACK确认。
    FIN_WAIT_2 表示收到了对方的ACK确认,等待对方的FIN报文。
    CLOSE_WAIT 表示收到了对方的FIN报文,等待从本地用户获取连接释放的确认。
    CLOSING 表示等待远端TCP对连接中断的确认。
    LAST_ACK 表示等待原始"关闭请求"的确认。
    TIME_WAIT 表示等待足够的时间以确保远端TCP接收到连接终止的确认。
    DELETE_TCB 一个不太常见的状态,表示清除传输控制块TCB,这是最后的清理阶段,不对外显示。

解决方案:

  • 应用层心跳:最常见的方法是在应用层实现心跳机制,即定期发送一些轻量级的数据包给对方,以确认对方是否还活着。如果心跳失败(例如,超时未收到响应),则可以认为对方已经不可达,此时可以关闭连接。
  • TCP Keepalive:TCP协议提供了一种机制叫做Keepalive,它可以在连接空闲时自动发送探测包,以检测对端是否还活着。Keepalive默认是关闭的,需要在socket编程时显式开启,并可以配置Keepalive探测包的发送频率和尝试次数。
  • 超时机制:在服务器程序中,可以为每个连接设置一个超时时间。如果在指定的超时时间内,没有收到任何数据,那么可以认为连接已经不再活跃,此时可以关闭该连接。这种方法需要根据应用的具体需求来调整超时时间的长短。
  • TCP RST包:在某些情况下,如果服务器检测到一个连接不再有效(例如,通过心跳机制),它可以主动发送一个TCP RST(重置)包给客户端。这个RST包会立即终止TCP连接,不需要经过正常的四次挥手过程。这种方法可以快速释放服务器资源,但可能会对客户端造成突然的连接中断。
  • 操作系统级别的参数调整:一些操作系统提供了调整TCP行为的参数,比如Linux的/proc/sys/net/ipv4/tcp_keepalive_time、tcp_keepalive_probes、tcp_keepalive_intvl等,这些可以全局影响系统的TCP Keepalive行为。调整这些参数可以帮助更好地管理长时间空闲的连接。
  • 使用负载均衡器或代理服务器:在复杂的网络架构中,负载均衡器或代理服务器可以帮助管理客户端和服务器之间的连接。它们可以定期检查后端服务器的健康状态,并在必要时重新分配或关闭无效的连接。这种方法对于大规模分布式系统尤其有用。
  • 利用应用框架或中间件的功能:一些高级的应用框架或网络中间件提供了内置的机制来管理TCP连接,包括自动的心跳检测、连接池管理和故障转移。使用这些功能可以减少开发者需要直接处理网络层面问题的复杂性。
  • 定期的连接验证任务:在某些应用中,可以设计一个定时任务,定期检查所有的TCP连接状态,并关闭那些被认为是不再活跃的连接。这种方法类似于应用层心跳,但是它是由服务器端集中管理,而不是依赖于客户端的活动。
相关推荐
恋猫de小郭32 分钟前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅7 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60618 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了8 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅8 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅9 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment9 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅9 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊9 小时前
jwt介绍
前端