📖 "三报文握手"建立 TCP 连接
🎯 课程摘要:本节课讲解 TCP 面向连接通信的三个阶段,重点详细剖析"三报文握手"建立 TCP 连接的完整过程(SYN → SYN+ACK → ACK),解释每个报文的序号 seq 与确认号 ack 的变化规律,并通过 408 考研真题说明为何必须三次握手而非两次(防止已失效的连接请求报文突然到达服务器而浪费资源)。
📝 详细笔记
1. TCP 运输连接的三个阶段
TCP 是面向连接的协议,基于运输连接来传送 TCP 报文段。每一次面向连接的通信包含以下三个阶段:
- 三报文握手建立 TCP 连接
- 基于已建立的 TCP 连接进行可靠的数据传输
- 四报文挥手释放 TCP 连接
2. 三报文握手的目的
建立 TCP 连接旨在解决以下三个主要问题:
- 使 TCP 双方能够确知对方的存在
- 使 TCP 双方能够协商一些参数(如最大报文段长度 MSS、最大窗口大小、时间戳选项等)
- 使 TCP 双方能够对运输实体资源进行分配和初始化(包括缓存大小、各状态变量、连接表中的项目等)
3. 三报文握手完整过程
初始状态
- 最初两端的 TCP 进程都处于关闭状态。
- TCP 服务器进程首先创建传输控制块(TCB),存储 TCP 连接中的重要信息(TCP 连接表、指向发送/接收缓存的指针、指向重传队列的指针、当前发送和接收序号等),之后进入监听状态,等待 TCP 客户进程的连接请求。由于服务器被动等待,称为被动打开连接。
- TCP 客户进程也要先创建传输控制块,打算建立连接时向服务器发送连接请求报文段。由于客户主动发起,称为主动打开连接。
三个报文段详解
| 报文 | 方向 | 标志位 | seq | ack | 状态变化 | 说明 |
|---|---|---|---|---|---|---|
| ① 连接请求报文段 | 客户 → 服务器 | SYN=1, ACK=0 | x | — | 客户进入同步已发送状态 | 不能携带数据,但消耗一个序号 |
| ② 连接请求确认报文段 | 服务器 → 客户 | SYN=1, ACK=1 | y | x+1 | 服务器进入同步已接收状态 | 对客户初始序号 x 的确认;不能携带数据,消耗一个序号 |
| ③ 普通确认报文段 | 客户 → 服务器 | ACK=1 | x+1 | y+1 | 双方都进入连接已建立状态 | 可携带数据;不携带数据则不消耗序号 |
关键规则
- SYN=1 的报文段不能携带数据,但要消耗掉一个序号。
- 普通的 TCP 确认报文段可以携带数据;若不携带数据,则不消耗序号。
- 报文 ① 序号 x 被消耗 → 报文 ③ 序号为 x+1。
- 报文 ③ 若不携带数据,客户下一次发送数据报文段的序号仍为 x+1。
Mermaid 时序图
4. 408 考研真题演练
真题一(2011 年,答案 C)
主机甲(TCP 客户)向主机乙(TCP 服务器)发送连接请求报文段:SYN=1,seq=11220。主机乙回复的连接请求确认报文段:SYN=1, ACK=1,ack=11221(= 11220 + 1),seq 为乙自选的初始序号(与其它值无关)。正确选项中 seq 恰好等于 ack 同为 11221 是迷惑项。
真题二(2019 年,答案 D)
主机甲发送连接请求报文段 seq=2018。主机乙回复连接请求确认报文段 seq=2046。主机甲发送的第三次握手 TCP 段(普通确认报文段)的确认号 ack=2047(= 2046 + 1)。
5. 为什么必须三报文握手而非两报文握手
- 答案:并不多余,不能简化为两报文握手。
两报文握手的问题(举例说明)
- TCP 客户进程发出一个连接请求报文段,但该报文段在某些网络节点长时间滞留,造成超时重传。
- 重传的连接请求报文段被服务器正常接收,服务器发送连接请求确认报文段并(因两报文握手)直接进入连接已建立状态。
- 客户收到后也进入连接已建立状态,双方传输数据后通过四报文挥手释放连接,进入关闭状态。
- 一段时间后,之前滞留的失效连接请求报文段到达服务器,服务器误认为是新的连接请求,发送确认并进入连接已建立状态。
- 客户进程并未发起新连接、处于关闭状态,不理睬该报文段。
- 服务器却一直处于连接已建立状态,等待客户发来数据,白白浪费服务器主机的大量资源。
- ⚠️ 重点/考点:采用三报文握手而非两报文握手建立 TCP 连接,是为了防止已失效的 TCP 连接请求报文段突然又传送到了服务器进程,因而导致错误。第三次握手确保双方都确认了对方的存在。
💡 核心总结
- 三报文握手:SYN=1(seq=x)→ SYN=1,ACK=1(seq=y, ack=x+1)→ ACK=1(seq=x+1, ack=y+1)。
- SYN=1 的报文段不携带数据但消耗一个序号;普通确认报文段不携带数据时不消耗序号。
- 服务器被动打开(监听)→ 同步已接收;客户主动打开 → 同步已发送 → 连接已建立。
- 第三次握手不可省略:防止失效的连接请求报文突然到达服务器而浪费资源。
❓ 课后思考 / 经典考题
- 三报文握手中,第二个报文段和第三个报文段的 seq 和 ack 分别如何取值?
- 为什么 SYN=1 的报文段不能携带数据但要消耗一个序号?普通确认报文段不携带数据时是否消耗序号?
- 若将三报文握手简化为两报文握手,会出现什么问题?请举例说明。
- (408 真题)主机甲发送连接请求 seq=2018,主机乙回复 seq=2046,则第三次握手报文段的确认号是多少?
- TCP 服务器进程和客户进程分别称为"被动打开"和"主动打开",原因是什么?