TCP 三次握手(建立连接)

核心目的
TCP 是可靠面向连接协议,三次握手用来:
- 确认双方发送能力、接收能力都正常
- 协商初始序列号
seq,为后续数据可靠传输做序号校验、丢包重传、乱序重组 - 防止失效旧连接报文干扰新连接
术语:
SYN:同步标志位,用于发起连接、协商初始序列号ACK:确认标志位,代表收到对方报文seq:本次发送数据包的序列号ack_seq:期望下一次收到对方的序列号 = 对方上一次 seq + 1
分步拆解三次握手(对应图上箭头)
第一次握手:客户端 → 服务端 SYN=1, seq=x
- 客户端状态变为:SYN_SEND(等待确认)
- 行为:客户端主动发 SYN 同步报文,随机生成初始序列号
x - 含义:客户端告诉服务端:我要建立连接,我的起始序号是 x
第二次握手:服务端 → 客户端 SYN=1,ACK=1,seq=y,ack_seq=x+1
- 服务端收到后状态:SYN_RECV(收到请求,等待客户端最后确认)
- 两个作用合并在一个报文里:
- SYN=1:服务端也同意建立连接,自己随机生成初始序列号
y - ACK=1:确认收到客户端的 SYN,期望下次收到序号
x+1
- SYN=1:服务端也同意建立连接,自己随机生成初始序列号
- 一句话:收到你的连接请求,我也同意建连,我的序号是 y
第三次握手:客户端 → 服务端 ACK=1,seq=x+1,ack_seq=y+1
- 客户端收到回复,状态切换为 ESTABLISHED(连接已建立)
- 客户端发送纯 ACK 确认报文,告诉服务端:我收到你的同意了
- 服务端收到这条 ACK,状态也变为 ESTABLISHED✅ 三次握手完成,TCP 通道正式打通,开始传输 HTTP 业务数据
TCP 四次挥手(断开连接)

核心目的
TCP 是全双工通信(客户端和服务端可以互相同时发数据),不能单方面一刀切断,必须分别关闭两个方向的数据流,所以需要四次挥手。
标志位
FIN:结束标志位,代表本端不再发送数据,请求关闭单向通道
分步拆解四次挥手(对应图箭头)
第一次挥手:客户端 → 服务端 FIN=1,seq=u
- 客户端数据全部发完,主动发起关闭请求,状态:FIN_WAIT_1(等待确认)
- 含义:客户端告诉服务器:我不会再给你发任何数据了,上游通道准备关闭
第二次挥手:服务端 → 客户端 ACK=1,seq=v,ack_seq=u+1
- 服务端收到 FIN,回复 ACK 确认,状态变为:CLOSE_WAIT(半关闭)
- 关键点:此时只是确认收到关闭通知,服务端还可以继续向客户端发送剩余未传完的数据(比如大文件后半段)
- 客户端收到 ACK,进入 FIN_WAIT_2(等待服务端彻底释放)
第三次挥手:服务端 → 客户端 FIN=1,ACK=1,seq=w,ack_seq=u+1
- 等服务端所有剩余数据全部发送完毕,主动发 FIN 报文,状态:LAST_ACK(等待最后确认)
- 含义:服务端告知客户端:我数据也发完了,我这边下行通道也要关闭了
第四次挥手:客户端 → 服务端 ACK=1,seq=u+1,ack_seq=w+1
- 客户端回复最后一次 ACK 确认报文,立刻进入 TIME_WAIT(等待一会) 状态,等待 2 个最大报文生存周期(2MSL)
- 服务端收到这条 ACK,直接变为 CLOSE,彻底关闭连接、释放端口
- 客户端等待 TIME_WAIT 超时后,最终也关闭连接
两个必考重点解释
1. 为什么挥手要四次,握手只需要三次?
- 握手:服务端的 SYN(同意建连)和 ACK(确认客户端)可以合并成一条报文,所以 2 次交互搞定;
- 挥手:服务端收到客户端 FIN 后,不能立刻发 FIN,必须先回复 ACK,等自己数据发完才能发 FIN,ACK 和 FIN 无法合并,因此必须四次。
2. 客户端为什么要有 TIME_WAIT 等待 2MSL?
两个作用:
- 保证最后一条 ACK 报文如果丢失,服务器超时重发 FIN,客户端还能再次补发 ACK,确保服务端正常关闭;
- 等待网络中残留的本次连接旧数据包全部过期消失,避免下一次新连接收到旧的错乱报文。