TCP的序列号与确认号机制详解
字数 1772 2025-11-25 15:43:14
TCP的序列号与确认号机制详解
描述:TCP的序列号和确认号是TCP可靠传输的核心机制。序列号用于标识每个报文段中数据的字节流位置,确认号用于告知对方已成功接收的数据。理解这两个编号的生成规则和交互逻辑,是掌握TCP可靠性的基础。
详细讲解:
-
基本概念:字节流编号
- TCP将应用层交付的数据视为一个无结构的、连续的字节流。
- 为了管理这个字节流,TCP为每个传输的字节分配一个唯一的序列号(Sequence Number, SEQ)。
- 序列号是一个32位的无符号整数,取值范围是0到2^32-1(约43亿)。当达到最大值后,会从0开始回绕。
-
初始序列号(Initial Sequence Number, ISN)的生成
- 在一个TCP连接开始时,通信双方需要为自己要发送的数据流选择一个起始序列号,即ISN。
- 为什么不能固定从0或1开始? 这是出于安全考虑。如果ISN是固定或可预测的,恶意攻击者可能伪造一个具有合法序列号的RST包来重置连接(连接重置攻击)。因此,ISN必须是随机的、不可预测的。
- 现代操作系统的ISN生成算法:通常基于一个复杂的公式,结合时间戳、散列函数等,确保其随机性和不可预测性。
-
三次握手阶段的序列号与确认号交换
这是理解SEQ和ACK号如何初始化和增长的关键。- 第一步(SYN):客户端发送一个SYN报文(标志位SYN=1)。这个报文会指定自己的初始序列号(ISN_c)。由于不携带应用数据,这个报文消耗一个序列号(下次发送数据时,序列号将从ISN_c+1开始)。此时确认号ACK为0。
- 第二步(SYN-ACK):服务器端回应一个SYN-ACK报文(SYN=1, ACK=1)。这个报文做两件事:
- 指定服务器端的初始序列号(ISN_s)。
- 确认客户端的SYN。确认号(Acknowledgment Number, ACK)的值为
客户端的ISN_c + 1。这个+1就是对客户端SYN报文本身的确认(因为SYN标志位消耗一个序列号)。
- 第三步(ACK):客户端发送一个ACK报文(ACK=1)。这个报文:
- 确认服务器的SYN。确认号(ACK)的值为
服务器端的ISN_s + 1。 - 此时可以开始携带应用数据。数据的第一个字节的序列号就是
ISN_c + 1。
- 确认服务器的SYN。确认号(ACK)的值为
-
数据传输阶段的序列号与确认号增长规则
假设连接已建立,客户端序列号为X,服务器端序列号为Y。- 规则一:序列号增长。发送方每发送N个字节的数据,其下一个报文的序列号就要增加N。
- 例:客户端发送一个数据段,序列号SEQ = X,数据长度Len = 100字节。那么,客户端发送的下一个数据段(如果是紧接着的)的序列号将是 X + 100。
- 规则二:确认号的含义。接收方发送的确认号ACK,表示“我期望收到的下一个字节的序列号”。这隐含了确认号之前的所有字节(即序列号小于ACK的所有字节)都已被成功接收。这种机制称为累计确认。
- 接上例:服务器成功收到客户端发来的100字节数据后,它回复的确认报文中的ACK号应为
X + 100。这个ACK号的含义是:“我已经成功收到了序列号到 X+99 的所有数据,现在我期待你从序列号 X+100 开始发送数据。”
- 接上例:服务器成功收到客户端发来的100字节数据后,它回复的确认报文中的ACK号应为
- 规则三:确认号本身不消耗序列号。纯ACK报文(不携带任何数据)不会导致自己的序列号增长。只有携带数据或SYN/FIN标志的报文才会消耗序列号。
- 规则一:序列号增长。发送方每发送N个字节的数据,其下一个报文的序列号就要增加N。
-
连接终止(四次挥手)中的序列号与确认号
- FIN标志位(表示发送方数据已发完)也消耗一个序列号。
- 假设客户端要关闭连接,其当前序列号为K。
- 客户端发送FIN报文(FIN=1),其序列号为SEQ = K。
- 服务器端收到后,回复ACK报文,确认号为ACK = K + 1。
- 当服务器端也发送FIN报文时,同样遵循上述规则。
总结:
TCP的序列号和确认号机制共同构成了可靠传输的基石。序列号确保了数据可按正确顺序重组,确认号则提供了接收情况的反馈。通过“下一个期望的序列号”这种累计确认方式,TCP可以高效地处理数据确认和重传,即使在出现包乱序或丢失的情况下,也能保证数据的完整性和有序性。理解 SEQ 和 ACK 的“+1”规则(对SYN/FIN的标志位确认)是掌握TCP交互细节的关键。