在大屏或电脑上体验更佳——动画和操作区域更宽敞。
输入

TCP 三次握手

常规 TCP 主动/被动打开使用 SYN、SYN-ACK、ACK 三个报文段,交换并确认双方初始序列号 ISN。两端各有状态机,并不在同一时刻完成建立。

可以把它看成确认双向信件编号:客户端说从 1000 开始,服务端确认下个期待 1001,并说自己从 5000 开始,客户端再确认期待 5001。每个方向的编号提议都得到对方确认。

握手如何工作

服务端先在 LISTEN,客户端为 CLOSED,尚无本次连接状态。客户端选择 ISN=1000,进入 SYN-SENT,发 SYN seq=1000。

服务端收到后建立本次连接状态,进入 SYN-RECEIVED,发送 SYN-ACK seq=5000, ack=1001:SYN 提议自己的起点,ACK 确认对方的起点。SYN 即使不带应用数据也占一个序列号,所以确认 1000 后期待 1001。

客户端接到 SYN-ACK,自己的 SYN 已获确认,进入 ESTABLISHED,再发 ACK seq=1001, ack=5001。服务端接收并接受最后 ACK 才进入 ESTABLISHED。两者之间存在客户端已建立、服务端仍等确认的窗口。

逐步演示

默认 clientIsn=1000、serverIsn=5000:

  1. 客户端 CLOSED,服务端 LISTEN。
  2. 客户端选择 1000,本次尝试保持这个起点。
  3. 客户端本地变 SYN-SENT,对方还未看见消息。
  4. 发 SYN seq=1000。
  5. SYN 到达服务端,先展示到达。
  6. 服务端变 SYN-RECEIVED,等待最终确认。
  7. 计算 ack=1001,确认 SYN 消耗的序号。
  8. 服务端选择 ISN=5000,它的 SYN 也占一号。
  9. 发 SYN-ACK seq=5000, ack=1001。
  10. 客户端收到,确认自己的 SYN。
  11. 客户端进入 ESTABLISHED,服务端仍等待。
  12. 客户端计算 ack=5001。
  13. 发最终 ACK seq=1001, ack=5001。
  14. 服务端收到该 ACK,在接受前仍显示 SYN-RECEIVED。
  15. 接受后服务端进入 ESTABLISHED。
  16. 本课建立完成,可传应用数据。

两条垂直生命线分别留下 CLOSED→SYN-SENT→ESTABLISHED 与 LISTEN→SYN-RECEIVED→ESTABLISHED。移动卡片标 flags、seq、ack,已交付的轨迹淡化,传输动作比记账动作留更长时间供读取。

为什么常规流程是三段

逻辑上有四项工作:客户端 SYN 提议、服务端 ACK 确认、服务端 SYN 提议、客户端 ACK 确认。中间两项合成 SYN-ACK,所以三段完成双向同步。缺最后 ACK,服务端还不知道自己的 SYN 是否被接受,会继续等待、重传或最终超时,不能据此宣布两端都完成。

这描述普通无数据握手,不要求所有 TCP 扩展或同时打开都只有同样三段。

边界情况

Lost SYN-ACK 在第 9 步后丢弃服务端回复。客户端保持 SYN-SENT,定时器到期后重传同一个 SYN seq=1000,不重新选择 ISN。

服务端在本课 SYN-RECEIVED 状态识别这次尝试的重复 SYN,不重复创建会话,重发同一 seq=5000, ack=1001。这次到达后,按第 10–16 步完成。单次丢失只增加本例耗时;持续丢失可能导致尝试超时,并非保证网络故障下总能建立。

连接也由双方地址与端口标识,不能只凭相同 ISN 判断连接身份;改变 ISN 也不意味着同一端点组合必定分配第二份连接。

常见错误

  • 把 ACK 当“刚收到的序号”。它表示下个期待序号,此处分别是 1001、5001。
  • 漏掉 SYN 占一号,让确认值差一。
  • 认为两端同时进入 ESTABLISHED。客户端收 SYN-ACK 后先完成,服务端还要等最终 ACK;半开状态是 SYN flood 等资源消耗问题的基础之一。
  • 把同次尝试的 SYN 重传当全新协商。端点组合与本次序列状态共同决定处理。
  • 认为 ISN 永远是整千。这里为可读性选 1000、5000,真实栈使用带不可预测性的选择规则并处理旧连接序列空间,降低旧包与伪造干扰。

模型范围

省略 TCP 选项、接收窗口、SYN cookies、同时打开、携带早期数据的扩展和基于 RTT 的实际超时估计。序列规则与常规状态路径用于教学,定时器简化。