TCP协议通信流程

TCP是一个面向连接的,安全的,流式传输协议,这个协议是一个传输层协议。

  • 面向连接:是一个双向连接,通过三次握手完成,断开连接需要通过四次挥手完成。
  • 安全:tcp通信过程中,会对发送的每一数据包都会进行校验, 如果发现数据丢失, 会自动重传
  • 流式传输:发送端和接收端处理数据的速度,数据的量都可以不一致

三次握手

TCP 协议的三次握手用于建立可靠的连接四次挥手用于关闭已建立的连接,两者是保障 TCP 面向连接、可靠传输的核心机制。

三次握手的目标是让客户端和服务端都确认对方的发送能力接收能力正常,并且双方协商好初始的序列号(ISN),为后续数据传输做准备。

核心角色:

  • 客户端:主动发起连接请求的一端。

  • 服务端:被动监听并接受连接请求的一端。

三次握手的具体过程:

  1. 第一次握手(客户端 → 服务端)
    • 客户端向服务端发送 SYN 报文(同步报文段),报文关键字段:
      • SYN=1:表示这是一个连接请求报文。
      • seq=x:客户端的初始序列号(ISN,随机生成)。
    • 此时客户端进入 SYN_SENT 状态,等待服务端响应。
    • 作用:客户端告诉服务端 “我有发送数据的能力,请求建立连接”。
  2. 第二次握手(服务端 → 客户端)
    • 服务端收到 SYN 报文后,确认自身接收能力正常,向客户端回复 SYN+ACK 报文,报文关键字段:
      • SYN=1:服务端也向客户端发起同步请求。
      • ACK=1:确认标志位,表明这是一个确认报文。
      • ack=x+1:确认号,等于客户端的序列号 + 1,表示服务端已正确接收客户端的 SYN 报文。
      • seq=y:服务端的初始序列号(随机生成)。
    • 此时服务端进入 SYN_RCVD 状态,等待客户端确认。
    • 作用:服务端告诉客户端 “我有接收和发送能力,已收到你的请求,也请你确认我的连接请求”。
  3. 第三次握手(客户端 → 服务端)
    • 客户端收到 SYN+ACK 报文后,确认服务端的发送和接收能力正常,向服务端发送 ACK 报文,报文关键字段:
      • ACK=1:确认标志位。
      • ack=y+1:确认号,等于服务端的序列号 + 1,表示客户端已正确接收服务端的 SYN 报文。
      • seq=x+1:客户端的序列号,基于第一次握手的 x 递增。
    • 客户端发送 ACK 后进入 ESTABLISHED(已建立连接)状态;服务端收到 ACK 后也进入 ESTABLISHED 状态。
    • 作用:客户端告诉服务端 “我已收到你的响应,连接正式建立”。

在这里插入图片描述

为什么需要三次握手?

核心是防止 “失效的连接请求报文” 被服务端接收,导致资源浪费:

假设客户端发送的 SYN 报文因网络延迟滞留,客户端超时后重发并建立连接、传输数据、关闭连接。

之后滞留的旧 SYN 报文到达服务端,若只有两次握手,服务端会直接建立新的连接并等待客户端发送数据,但客户端根本不会理会,服务端会一直维护这个无效连接,浪费资源。

二次握手就可以建立链接,三次握手是为了防止丢包的链接被服务端等待:

三次握手时,服务端需要等待客户端的第三次 ACK 确认,旧的 SYN 报文不会收到客户端的 ACK,服务端会超时释放资源。

为什么三次握手需要确认号(ack)和序列号(seq)

TCP 三次握手时发送序列号(seq)确认号(ack),核心目的是为后续的可靠数据传输打下基础 —— 这两个字段是 TCP 实现有序传输、去重、重传等核心功能的关键,也是连接双方确认彼此收发能力的核心依据。

有了seq 和 ack,此时双方才能实时监控信息传输进度,自动过滤重复信息 或 确认丢失数据。

seqack 的这个作用,是从三次握手同步初始序号后才正式生效的。三次握手的核心就是让双方确认彼此的初始 seq(ISN),只有初始序号同步了,后续数据传输的 seq 递增、ack 反馈才有统一的基准,上述的进度监控、去重、重传逻辑才能正常运转。

  1. 序列号(seq)
    • 标识当前报文本身的起始编号,是一个随机生成的 32 位整数(称为初始序列号 ISN)。
    • 后续传输数据时,每个字节都会被分配一个序号,seq 就是当前报文第一个字节的编号。
    • 三次握手阶段,seq 用于同步双方的初始序号基准。
  2. 确认号(ack)
    • 标识期望收到的下一个字节的序号,等于已成功接收的最高序号 + 1
    • 只有当报文中的 ACK=1 时,ack 字段才有效;ACK=0 时,ack 无意义。
    • 三次握手阶段,ack 用于告诉对方 “我已收到你的报文,请你下次从这个序号开始发送”。

三次握手的核心目标之一,是让客户端和服务端都确认 “对方能正常发,我能正常收;我能正常发,对方能正常收”。而 seq 和 ack 就是验证这个能力的关键:

  • 服务端能正确返回 ack=x+1,说明客户端的发送能力正常(服务端收到了客户端的 SYN 报文),且服务端的发送能力正常(能发出带 ack 的报文)。
  • 客户端能正确返回 ack=y+1,说明服务端的发送能力正常(客户端收到了服务端的 SYN+ACK 报文),且客户端的确认能力正常

如果没有 seq 和 ack,双方只能确认 “报文收到了”,但无法确认 “后续数据该怎么编号”,更无法验证完整的收发链路。

如果三次握手不携带这两个字段,TCP 连接会存在的致命问题:

  1. 数据传输无序:后续发送的报文段没有编号,接收方无法判断报文的先后顺序,可能出现 “后发的数据先到” 的混乱。
  2. 无法重传和去重:接收方无法确认哪些数据丢了、哪些数据重复了,TCP 的可靠传输就无从谈起。
  3. 旧连接请求泛滥:大量失效的旧 SYN 报文会建立无效连接,耗尽服务端资源。

四次挥手

TCP 是全双工通信(双方可同时收发数据),关闭连接时,需要双方分别关闭自己的发送通道,因此需要四次交互。

核心前提

  • 连接关闭可由客户端或服务端主动发起,以下以客户端主动关闭为例。
  • TCP 报文的 FIN 标志位表示 “数据发送完毕,请求关闭发送通道”。
  1. 第一次挥手(客户端 → 服务端)
    • 客户端主动关闭连接,向服务端发送 FIN 报文,报文关键字段:
      • FIN=1:表示客户端没有数据要发送了,请求关闭发送通道。
      • seq=u:客户端当前的序列号(累计之前传输的数据后的序号)。
    • 客户端进入 FIN_WAIT_1 状态,等待服务端的确认。
    • 作用:客户端告诉服务端 “我不再向你发送数据了”。
  2. 第二次挥手(服务端 → 客户端)
    • 服务端收到 FIN 报文后,向客户端回复 ACK 报文,报文关键字段:
      • ACK=1:确认标志位。
      • ack=u+1:确认号,等于客户端的 FIN 序列号 + 1。
      • seq=v:服务端当前的序列号。
    • 服务端进入 CLOSE_WAIT 状态;客户端收到 ACK 后进入 FIN_WAIT_2 状态。
    • 作用:服务端告诉客户端 “我已收到你的关闭请求,你可以停止发送数据了,但我可能还有数据要发给你”。
    • 此时客户端到服务端的发送通道已关闭,但服务端到客户端的发送通道仍可传输数据。
  3. 第三次挥手(服务端 → 客户端)
    • 服务端将剩余数据发送完毕后,向客户端发送 FIN 报文,报文关键字段:
      • FIN=1:表示服务端也没有数据要发送了,请求关闭自己的发送通道。
      • ACK=1:确认标志位。
      • ack=u+1:沿用之前的确认号。
      • seq=w:服务端发送完剩余数据后的序列号。
    • 服务端进入 LAST_ACK 状态,等待客户端的确认。
    • 作用:服务端告诉客户端 “我也没有数据要发送了,请求关闭我到你的发送通道”。
  4. 第四次挥手(客户端 → 服务端)
    • 客户端收到 FIN 报文后,向服务端回复 ACK 报文,报文关键字段:
      • ACK=1:确认标志位。
      • ack=w+1:确认号,等于服务端的 FIN 序列号 + 1。
      • seq=u+1:客户端当前的序列号。
    • 客户端发送 ACK 后进入 TIME_WAIT 状态(等待 2MSL 时间后才会进入 CLOSED 状态);服务端收到 ACK 后直接进入 CLOSED 状态。
    • 作用:客户端告诉服务端 “我已收到你的关闭请求,连接即将完全关闭”。

在这里插入图片描述

TIME_WAIT 状态与 2MSL
  • MgSL(Maximum Segment Lifetime):报文在网络中的最大生存时间,超过该时间报文会被丢弃。
  • 客户端发送第四次 ACK 后,需要等待 2MSL 时间:
    1. 确保服务端能收到第四次的 ACK 报文。如果服务端没收到,会重发第三次的 FIN 报文,客户端在 2MSL 内收到后会重新发送 ACK,并刷新等待时间。
    2. 确保本次连接的所有报文都从网络中消失,避免新连接收到旧连接的残留报文。
为什么要四次挥手,三次挥手可以吗?

TCP 连接是全双工的,意味着客户端和服务端可以同时双向收发数据,两个方向的数据流是相互独立的。关闭连接不是 “一刀切断”,而是要分两步:

  1. 关闭 A→B 的发送通道;
  2. 关闭 B→A 的发送通道。

只有两个方向都关闭,连接才算真正关闭。

步骤 发起方 报文 核心目的
1 客户端 → 服务端 FIN 客户端说:我不再给你发数据了(关闭自己的发送通道),但我还能接收你的数据
2 服务端 → 客户端 ACK 服务端说:我收到你的关闭请求了,我还有数据要发,你等我发完
3 服务端 → 客户端 FIN 服务端说:我也不给你发数据了(关闭自己的发送通道)
4 客户端 → 服务端 ACK 客户端说:我收到你的关闭请求了,连接可以彻底关闭了
  • 三次挥手:指建立连接时,只需要双方确认 “收发能力正常 + 同步序列号”,一次 SYN+ACK 就能完成双向同步。

正常来说三次挥手无法满足数据的完整传输,如果第三次挥手时,另一方还有未发送完的数据,此时立即关闭传输会导致数据的传输失败,但是当另一方收到第二次挥手信号时,已经没有多余的数据进行传输,此时可以进一步优化为三次挥手。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐