从 TCP 要解决的问题出发,理解三次握手、四次挥手、可靠传输和 TIME_WAIT。
TCP 是传输层协议,核心目标是:在不可靠的网络之上,尽量提供可靠、有序、面向连接的数据传输。
它比 UDP 多做了很多事情,比如建立连接、确认数据、超时重传、流量控制、拥塞控制。三次握手和四次挥手,就是 TCP 管理连接生命周期的两个关键过程。
TCP 解决什么问题
网络本身并不保证数据一定能到达。数据包可能丢失、乱序、重复,也可能因为网络拥塞而延迟。
TCP 主要通过这些机制提高可靠性:
- 序列号:给每段数据编号,用来判断顺序和去重
- 确认应答:接收方收到数据后返回 ACK,告诉发送方已经收到
- 超时重传:发送方长时间收不到 ACK,会重新发送数据
- 流量控制:接收方告诉发送方自己还能接收多少数据,避免被打爆
- 拥塞控制:根据网络情况调整发送速度,避免把网络打满
所以 TCP 不是“绝对可靠”,而是在 IP 这种尽力而为的网络之上,提供一套可靠传输机制。
三次握手
三次握手的目的不是单纯“打个招呼”,而是确认双方都具备发送和接收能力,并同步初始序列号。
可以先用类比理解:
- 客户端:我能发消息,你能收到吗?
- 服务端:我收到了。你也能收到我发的消息吗?
- 客户端:我收到了,我们开始通信吧。
对应到 TCP 报文,大致是:
客户端 -> 服务端: SYN, seq = x
服务端 -> 客户端: SYN + ACK, seq = y, ack = x + 1
客户端 -> 服务端: ACK, ack = y + 1
第一次握手
客户端发送 SYN 报文,表示希望建立连接,并带上自己的初始序列号 seq = x。
此时客户端进入 SYN_SENT 状态。
第二次握手
服务端收到 SYN 后,返回 SYN + ACK:
ACK表示已经收到客户端的SYNack = x + 1表示期望客户端下次从x + 1开始发送SYN表示服务端也要同步自己的初始序列号seq = y
此时服务端进入 SYN_RECEIVED 状态。
第三次握手
客户端收到服务端的 SYN + ACK 后,再发送一个 ACK,确认自己收到了服务端的初始序列号。
这一步完成后,客户端和服务端都进入 ESTABLISHED 状态,连接建立完成。
为什么是三次握手
两次握手只能证明:
- 服务端能收到客户端的数据
- 客户端能收到服务端的数据
但服务端还不能确认:客户端是否真的收到了自己的 SYN + ACK。
第三次握手的价值就在这里:让服务端确认客户端的接收能力正常,同时避免历史连接请求因为网络延迟突然到达,导致服务端误建连接。
一句话总结:
三次握手是为了确认双方的发送和接收能力都正常,并同步双方的初始序列号。
四次挥手
TCP 是全双工通信。也就是说,客户端和服务端两边都可以同时发送数据。
关闭连接时,不能简单地一方说“我不发了”,另一方就立刻断开。因为一方停止发送数据,不代表另一方的数据也已经发完。
可以先用类比理解:
- 客户端:我这边数据发完了,准备关闭。
- 服务端:我知道了,但我可能还有数据没发完。
- 服务端:我这边也发完了,可以关闭。
- 客户端:收到,那连接关闭。
对应到 TCP 报文,大致是:
客户端 -> 服务端: FIN
服务端 -> 客户端: ACK
服务端 -> 客户端: FIN
客户端 -> 服务端: ACK
第一次挥手
主动关闭方发送 FIN,表示自己已经没有数据要发送了。
注意:发送 FIN 只代表这一侧不再发送数据,但仍然可以接收对方的数据。
第二次挥手
被动关闭方收到 FIN 后,先返回 ACK,表示已经知道对方要关闭发送方向。
此时被动关闭方可能还有数据没发送完,所以不能立刻发送 FIN。
第三次挥手
被动关闭方把剩余数据发送完后,再发送 FIN,表示自己也没有数据要发送了。
第四次挥手
主动关闭方收到 FIN 后,返回 ACK。被动关闭方收到这个 ACK 后关闭连接。
主动关闭方不会马上消失,而是进入 TIME_WAIT 状态,等待一段时间后才真正关闭。
为什么需要 TIME_WAIT
TIME_WAIT 主要有两个作用:
- 确保最后一个 ACK 能到达对方:如果最后的 ACK 丢了,对方会重发 FIN,主动关闭方还可以再回 ACK
- 避免旧连接的数据影响新连接:等待网络中旧连接的报文自然过期,防止它们混入后续新连接
所以 TIME_WAIT 不是无意义的等待,而是 TCP 为了可靠关闭连接付出的成本。
三次握手和四次挥手的区别
| 过程 | 目的 | 为什么是这个次数 |
|---|---|---|
| 三次握手 | 建立连接,确认双方收发能力,同步初始序列号 | 第三次握手让服务端确认客户端能收到自己的响应 |
| 四次挥手 | 关闭连接,分别关闭两个方向的数据传输 | TCP 是全双工连接,一方不发了,不代表另一方也发完了 |
常见问题
为什么建立连接是三次,关闭连接是四次
建立连接时,服务端可以把 SYN 和 ACK 合并在同一个报文中返回,所以是三次。
关闭连接时,收到 FIN 的一方通常还可能有数据没发送完,只能先回 ACK,等数据发送完后再单独发送 FIN,所以通常是四次。
TCP 一定比 UDP 好吗
不一定。
TCP 适合需要可靠、有序传输的场景,比如网页、接口请求、文件传输。UDP 更适合低延迟、允许少量丢包的场景,比如直播、语音、游戏、DNS 查询。
选择 TCP 还是 UDP,不是看哪个“更高级”,而是看业务更需要可靠性还是实时性。
总结
TCP 的重点不是背诵“三次握手、四次挥手”,而是理解它们分别在解决什么问题:
- 三次握手:确认双方收发能力正常,并同步初始序列号
- 四次挥手:分别关闭两个方向的数据传输
TIME_WAIT:保证连接可靠关闭,并避免旧报文影响新连接- 可靠传输:依赖序列号、ACK、重传、流量控制和拥塞控制共同完成