一、什么是 TCP 三次握手?
🔴TCP(Transmission Control Protocol,传输控制协议)是🔴一种面向连接的、可靠的、基于字节流的传输层协议
在正式传输数据之前,通信双方需要先建立 TCP 连接。这个过程称为 🔴**TCP 三次握手(Three-Way Handshake)**
简单来说,三次握手就是客户端和服务器通过三次 TCP 报文交换,确认双方的收发能力,并同步各自的初始序列号,从而建立连接
可以把它理解为🔵两个人打电话前的确认过程:
客户端:喂喂喂,能听到吗?
服务器:能听到,你说吧
客户端:好的,巴拉巴拉…
当然啦,这只是帮助理解的类比(✌ TCP 三次握手真正要完成的是双方初始序列号的同步,以及对彼此通信能力的确认 
-
SYN:同步序列号,用于发起连接并同步初始序列号
-
ACK:确认标志,表示报文中的确认号有效
-
Seq:序列号,标识本端发送的数据序列位置
-
Ack:确认号,表示本端下一步期望接收的序列号
这里的 x 和 y 分别代表客户端和服务器选择的初始序列号(ISN,Initial Sequence Number)
二.TCP 三次握手的具体过程
第一次握手:(客户端->服务器)
客户端发送一个SYN=1的同步报文,携带初始序列号seq=x,进入SYN_SENT状态
此报文表示"我准备从初始序列号 x 开始发送数据,请确认你收到了我的请求“ 但此时服务器尚未确认客户端的连接情况 此时:
-
客户端状态:SYN-SENT
-
服务器状态:LISTEN
SYN-SENT 表示客户端已经发送连接请求,正在等待服务器的响应 LISTEN 表示服务器正在监听端口,等待客户端发起连接 第一次握手的核心:客户端发起连接请求,并向服务器告知自己的初始序列号
第二次握手:(服务器->客户端)
服务器收到SYN后,回复一个SYN=1且ACK=1的报文,携带自己的初始序列号seq=y 并确认客户端的序列号Ack=x+1,进入SYN_RECV状态 这个报文同时完成两件事: 一,确认客户端的请求 Ack = x + 1 表示服务器已经收到客户端的 SYN,并期望接收客户端序列号为 x + 1 的后续内容。
二,向客户端发起自己的序列号同步 Seq = y 表示服务器选择的初始序列号为 y
为什么确认号是 x + 1,而不是 x? 因为 TCP 规定,SYN 标志会占用一个序列号。即使这个报文没有携带应用层数据,也需要将序列号向前推进一位
此时:
-
服务器状态:SYN-RECEIVED
-
客户端仍在等待最后的确认
第二次握手的核心:服务器确认收到了客户端的连接请求,同时向客户端提供自己的初始序列号 此报文表示"我收到了你的请求,我也准备好了,确认你已发送"
第三次握手:(客户端->服务器)
客户端收到SYN+ACK时,回复一个ACK=1且Ack=y+1的报文,seq=x+1 这表示客户端已经收到服务器的 SYN,并确认服务器的初始序列号 y 其中:
-
Seq = x + 1:客户端接下来使用的序列号。
-
Ack = y + 1:客户端期望接收服务器序列号为 y + 1 的后续内容
客户端发送这个ACK后,进入ESTABLISHED状态。服务器收到后也进入ESTABLISHED状态,连接正式建立,双方可开始数据传输 第三次握手的核心:客户端确认收到了服务器的初始序列号,完成双方序列号的同步
三.初始序列号与确认号详解
为什么需要同步初始序列号?
TCP 是可靠传输协议,需要通过序列号和确认号跟踪数据的发送与接收 假设客户端选择的初始序列号为 100,服务器选择的初始序列号为 400 那么,正常握手过程如下:
| 第一次 | 客户端 | 100 | 未启用 |
| 第二次 | 服务器 | 400 | 101 |
| 第三次 | 客户端 | 101 | 401 |
通过这个过程:
-
服务器确认客户端的 SYN,知道客户端初始序列号为 100
-
客户端确认服务器的 SYN,知道服务器初始序列号为 400
-
双方都知道对方已经确认了自己的初始序列号
这里有两个容易混淆的细节: 1. SYN 会消耗一个序列号 因此,确认序列号 100 的 SYN 时,确认号应当是 101
2. 纯 ACK 不会消耗序列号 第三次握手的 ACK 本身不会让客户端的发送序列号额外增加一位。如果后续没有发送数据,客户端后续报文仍可以从序列号 101 开始
这也是为什么握手过程中会出现 x + 1 和 y + 1
四.为什么是三次握手?
1.为什么不能简化为两次握手?
两次握手无法完成标准 TCP 连接建立所需的全部确认过程
客户端发送 SYN,告知服务器自己的初始序列号 x。
服务器回复 SYN + ACK,确认客户端的 SYN,并告知自己的初始序列号 y。
此时,服务器已经向客户端发送了自己的 SYN,但还没有收到客户端对该 SYN 的最终确认。如果此时就认为连接已经完全建立,服务器就无法确认客户端是否真正收到了自己的连接响应
此外,网络中可能存在延迟到达的旧 SYN 报文。如果服务器仅凭两次报文交换就完成连接建立,可能会错误地为过期请求建立连接状态
因此,第三次握手的关键作用是:让服务器确认客户端收到了自己的 SYN + ACK,并完成双方初始序列号的确认过程
但这并不意味着 TCP 在连接建立阶段绝对不能携带数据。标准 TCP 允许特定场景下在 SYN 报文中携带数据,但普通应用通常在连接建立后进行常规数据传输
2. 为什么不需要四次握手?
第二次握手中的 SYN 和 ACK 可以放在同一个 TCP 报文中 服务器一方面需要确认客户端的 SYN,另一方面需要发送自己的 SYN。由于这两个动作可以合并到一个报文中,所以不必拆成两次发送 因此,正常建立 TCP 连接只需要三次握手,而不是四次
3. 三次握手究竟确认了什么?
可以从三个方面理解:
-
确认通信能力: 客户端发送的 SYN 被服务器收到,服务器发送的 SYN + ACK 被客户端收到,客户端最后发送的 ACK 可以让服务器确认客户端收到了自己的响应。
-
同步初始序列号: 双方交换各自的初始序列号,并确认对方的初始序列号。
-
建立一致的连接状态: 双方按照握手过程转换状态,进入正常的数据传输阶段。
三次握手不等同于对服务器业务功能可用性的全面检查。它建立的是 TCP 连接,并不保证应用程序一定能够正常处理业务请求
五.TCP 三次握手面试高频考点
考点一:三次握手能否保证 TCP 数据一定可靠到达?
不能 三次握手的主要任务是建立连接及同步初始序列号,并不是保证未来所有数据一定送达 TCP 的可靠传输还依赖序列号、确认应答、重传、接收窗口、流量控制和拥塞控制等机制。连接建立成功,只代表连接已经建立,不代表后续传输不会发生丢包或延迟
考点二:三次握手分别发送了什么?
第一次,客户端发送 SYN,携带客户端初始序列号 x 第二次,服务器发送 SYN + ACK,携带自己的初始序列号 y,并通过 Ack = x + 1 确认客户端的 SYN 第三次,客户端发送 ACK,通过 Ack = y + 1 确认服务器的 SYN。此后双方进入 ESTABLISHED 状态
考点三:为什么 SYN 会使序列号加一?
TCP 的 SYN 和 FIN 都会各自占用一个序列号,即使不携带应用层数据也一样。因此,客户端发送 Seq = x 的 SYN 后,服务器确认它时使用 Ack = x + 1。服务器的 SYN 同理,也会使客户端的确认号增加一
考点四:第三次握手可以携带数据吗?
可以,但需要区分 TCP 协议本身的能力与常见实现的行为 在常见的普通三次握手场景中,第三次报文通常只是 ACK,不携带应用层数据 从 TCP 协议角度看,在满足相应连接状态及序列号处理要求时,第三次 ACK 可以携带数据。接收端必须按照 TCP 的规则处理这些数据,而不能仅凭收到报文就忽略序列号和连接状态检查
考点五:如果第三次握手的 ACK 丢失,会怎么样?
假设客户端已经发送第三次 ACK,但这个报文在网络中丢失:
客户端可能已经进入 ESTABLISHED 状态
服务器仍停留在 SYN-RECEIVED 状态,因为它还没有收到最后的 ACK
服务器会根据 TCP 的重传机制,在适当条件下重传 SYN + ACK
客户端收到重复的 SYN + ACK 后,通常会再次发送 ACK
如果服务器最终收到有效 ACK,就能完成连接建立;如果一直收不到,则可能在重试或超时后清理未完成的连接状态
因此,第三次握手丢失不意味着连接必然立即失败,但会造成双方暂时处于不同的连接状态
考点六:什么是 SYN Flood 攻击?
SYN Flood 是一种利用 TCP 连接建立机制的拒绝服务攻击 攻击者大量发送 SYN 请求,却不完成后续握手,导致服务器需要维护大量未完成的连接请求状态,从而消耗资源 常见防护手段包括 SYN Cookies、连接请求队列与超时参数优化,以及适当的限流和网络防护措施 三次握手本身不是完整的安全防护机制,它不能单独阻止 SYN Flood 攻击
参考资料
-
RFC 9293:Transmission Control Protocol (TCP)。重点参考连接建立、初始序列号、状态机和数据传输规则
-
MDN:TCP handshake。快速回顾握手流程。




