TCP 三次握手到底在握什么:一次讲透

从「打个电话」理解连接建立的全过程

作者 sunhao666 · 2026年9月30日 · 约 3 分钟

为什么需要握手#

网络上两台电脑要可靠地传数据,第一步是确认「双方都能发、也都能收」。 这件事听起来简单,但在只有单向不可靠信道的前提下,需要三次交互才能确定。

用一个生活场景类比:你给同学打电话。

  1. 第一次握手:你拨号,同学电话响了 —— 他知道了「你的耳朵和嘴巴都好使」
  2. 第二次握手:同学接起来说「喂」 —— 你知道了「他的耳朵和嘴巴都好使」,他也知道了「你听得见」
  3. 第三次握手:你说「听到了,开始聊」 —— 他知道了「你确实听得到」

到这一步,双方才同时确认了四件事:自己能发、自己能收、对方能发、对方能收。

报文里的关键字段#

字段 作用 握手时怎么变
SYN 请求建立连接 第 1、2 次置 1
ACK 确认收到 第 2、3 次置 1
seq 自己的序号 随机生成,防止旧连接串味
ack 期望对方下次发的序号 等于对方 seq + 1

为什么是三次而不是两次#

这是考试的高频考点,也是理解的关键。

假设只有两次握手,那么服务端一收到 SYN 就认为连接建立了。问题在于: 网络中会滞留一些「过期的连接请求」。如果客户端早就放弃了, 而服务端收到这个迟到的 SYN 后直接建连接,就会白白占用资源等着一个不会来的客户端。

第三次握手的作用,就是让服务端在真正开始工作前,再确认一次客户端还在。

记忆口诀:两次握手只能确认「对方能收」,三次才能确认「对方也想连」。

为什么要随机初始序号#

如果每次都从 0 开始编号,那么上一次连接里滞留在网络中的旧数据包, 可能被误认为这次连接的数据。随机化初始序号后,这种概率就变得可以忽略。

用代码观察握手#

想让同学亲眼看到握手过程,可以用 Python 抓包:

import socket

# 创建一个 TCP 客户端
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 这一步的三方交互,就是三次握手
# 抓包时你会依次看到 SYN、SYN+ACK、ACK 三个包
client.connect(("www.example.com", 80))

print("连接已建立,三次握手完成")
client.close()

配合 Wireshark 过滤 tcp.flags.syn == 1,就能在课堂上实时演示。

课堂思考题#

  1. 如果第三次握手的 ACK 丢了,服务端会怎么办?
  2. 为什么初始序号不直接用 0,而要用随机数?
  3. 四次挥手为什么比三次握手多一次?

小结#

次数 方向 携带标志 真正确认了什么
1 客户端 → 服务端 SYN 服务端知道客户端能发
2 服务端 → 客户端 SYN + ACK 客户端知道双方收发都正常
3 客户端 → 服务端 ACK 服务端确认客户端仍在,连接可用
附件下载(1 个)
PDF test 4.7 MB · 已下载 1 次