TCP的核心组件(上):说说TCP序列号的运动规律

科技   2024-12-17 11:18   上海  

本系列的前两篇文章和大家聊了关于TCP连接建立成功与失败的情况,本文将围绕一个新的话题进行着重探讨——TCP序列号(Sequence Number)、载荷长度(Payload Length)和下一包序列号(Next Sequence Number)。

  TCP的“序列号”是什么?

TCP协议为了实现可靠传输,将它自己要发送的每一个字节都进行了“排序编号”。例如,当发送方要发送一个字符a时,字符a会被赋予一个序列号(Sequence Number),例如1234567890。在TCP协议中,序列号的取值范围为0-4296947295,关于TCP的序列号,在时序图中可通过如下位置直接观察:

图1:时序图中的“序列号”

  TCP连接启动阶段,序列号如何确定?

万物皆有源,TCP连接建立的初始包,序列号应该从哪个数字开始?这要引入一个概念:ISN(启动序列号,Initial Sequence Number),ISN即客户端和服务器在会话首包使用的序列号,客户端与服务器使用的ISN号码是不同的。根据RFC 793的描述,产生ISN数字的算法应该尽可能的随机,从而避免序列号的冲突和序列号被攻击者猜测。

因此,客户端的ISN即SYN包的序列号,服务器的ISN即SYN/ACK包的序列号,ISN的位置如图2所示。

图2:时序图中的“ISN”

  TCP的“载荷长度”和“下一包序列号”又是什么?

要理解TCP的序列号如何工作,需要引入另外两个概念:载荷长度和下一包序列号。

载荷长度(Payload Length)为一个TCP数据包的载荷数据长度,即数据包不含二层、三层、四层数据的长度。时序图的右侧标记了每一个TCP数据包的载荷长度。通过图2可以看出,4号包的载荷长度为138,6号包的载荷长度为68,其它包由于仅为基础TCP交互,并未传输应用层数据,因此不存在载荷长度,如图3所示:

图3:时序图中的“载荷长度”

下一包序列号(Next Sequence Number)为该数据包之后下一个数据包的序列号,计算方式为【当前包的序列号+载荷长度=下一包序列号】。时序图中每一数据包的序列号右侧显示了经过计算的,该包的下一包序列号。如图4所示:

图4:时序图中的的“下一包序列号”

需要注意的是,序列号的编号单位是基于字节,而不是基于数据包。

  TCP序列号为何有时+1,有时+长度?

刚才说到,【当前包的序列号+载荷长度=下一包序列号】,看到这里可能会有细心读者问,图中1号SYN包和7号FIN包并不存在载荷长度,为何下一包序列号被设置为序列号+1?

这是由于SYN包和FIN包为连接中较重要的包,需要被确认,因此数据包的SYN位和FIN位被TCP视为1字节的载荷数据。所以,在TCP三次握手中,客户端SYN和服务器SYN/ACK包的下一包序列号为【当前包的序列号(ISN)+载荷长度(1字节SYN位)=下一包序列号(ISN+1)】。如下图所示:

图5:三次握手中的“下一包序列号”

大多数人理解TCP两个连续包之间的序列号是+1方式递增,其实这是一种理解误区。如果一定要按照+1增长方式来理解TCP序列号,可理解为:连接建立和断开阶段的下一包序列号为【序列号+1】,数据传输阶段的下一包序列号为【序列号+长度】

  从时序图看TCP序列号的运动规律  

理解了上述概念后,我们再来根据【序列号+载荷长度=下一包序列号】这一公式梳理一下TCP的是如何安排序列号的。以下图为例:

图6:TCP序列号的运动规律

  • 1号包为客户端发往服务器方向的首包,序列号为1638701981,即客户端ISN,载荷长度为一个SYN位,因此下一包序列号为1638701981+1=1638701982。因此,1号包的下一包序列号为1638701982。
  • 3号包同样为客户端发往服务器方向,序列号为1638701982,该包不存在载荷数据,因此,3号包的下一包序列号为1638701982+0,仍为1638701982。
  • 接下来,客户端发送了4号包,其序列号为1638701982,该包载荷长度为138字节,因此,4号包的下一包序列号为1638701982+138=1638702120
  • 最后,客户端发送了7号包,其序列号为1638702120,该包载荷为一个FIN位,因此下一包序列号为1638702120+1=1638702121
  • 2号包为服务器发往客户端方向的首包,序列号为432609823,即服务器ISN,载荷长度为一个SYN位,因此下一包序列号为432609823+1=432609824。因此,2号包的下一包序列号为432609824
  • 5号包同样为服务器发往客户端方向,序列号为432609824,该包不存在载荷数据,因此,5号包的下一包序列号为432609824+0,仍为432609824。
  • 接下来,服务器发送了6号包,其序列号仍为432609824,该包载荷长度为68字节,因此,6号包的下一包序列号应为432609824+68=432609892。

以上即是TCP序列号的运动规律。看到这里,你是否已经加深了对TCP序列号运动规律的理解?

本文中深入探讨了TCP序列号的概念,从时序图的视角揭示了序列号的运动规律。除序列号外,确认号也是TCP连接中另一个关键概念,确认号与序列号一起构成了TCP可靠传输的基础。

来自科来公众号

Qt教程
致力于Qt教程,Qt技术交流,研发
 最新文章