理解Tcp序列号和确认号

如果见过Tcp的数据封包格式,那么一定会对它首部中的32位序列号和确认号有一定的印象。此篇笔记就是真正理解这两个号码段的作用,因为按以往的话总是停留在什么‘序号+1’的认知,却说不出个所以然。

我们都知道TCP之所以可靠,是因为它保证了传送数据包的顺序。而顺序就是用一个序列号来保证的。另外,TCP通过数据分段中的序列号来保证所有传输的数据可以按照正常的顺序进行重组,从而保障数据传输的完整。下面我们用网上的一个例子来说明序列号和确认号是怎么保证顺序的:本机地址(0.92)作客户端,去连接外网(222.77.187.23)的服务器端。

我们将其抓包,首先是Tcp三次握手中的第一次,如图:

从图中我们可以看到,客户端的初次请求连接的syn包里面,它的初始序列号(ISN)为2712239078,这是一个客户端随机产生的一个值,之所以随机是因为出于网络安全的因素,如果不是随机产生初始序列号,黑客将会以很容易的方式获取到你与其他主机之间通信的初始化序列号,并且伪造序列号进行攻击!然后它的确认号是0(因为它是第一条不需要确认什么,故为0)。

接着是服务器收到客户端请求后,发回的ACK确认,如图:

这个发回给客户端的ACK确认包中,它的初始化序列号是1288781508,和客户端一样它是服务器端随机产生的值,接着是确认号,显示的是2712239079。都应该可看出它是(2712239078 + 1),即客户端的初始序列号+1(虽然该包没有数据,但syn标志消耗了一个序号+1)。表示说,客户端你下一次发的数据包里面,序列号是2712239079开始。

最后是客户端收到服务端发回的Ack后,再向服务器发的最后1次连接确认,如图:

三次握手中的最后一个数据包我们可以看到,客户端发的序列号为2712239079(它是上一次服务器发回希望客户端发的序列号),确认号是1288781509(1288781508 + 1),即服务器端的初始序列号+1。表示说,服务端你下一次发的数据包里面,序列号是1288781509开始。

介绍完了握手之后,来看看客户端向服务器发送数据的时候序列号和确认号的变化:

从图中来看,该数据包序列号为2712239079,确认号为1288781509,这和三次握手的最后1步两个号码都是一样的。还有我们观察到这个数据包的大小为1018Byte,那么我们做一个算法,让它减去14字节的以太网报头,20字节的IP报头,20字节的TCP报头,4字节的FCS,最后得出这个包真正的数据大小为:1018-14-20-20-4=960。所以说,按照TCP协议的规定,如果服务器正常收到这些数据,那么它返回过来的包里面的确认号应该是:2712239079 + 960 = 2712240039。

我们看看不就知道咯~如图:

怎么样,可以看到此包中序列号为1288781509,而确认号正是上面所计算出来的2712240039。综上我们知道了每个过程完成了不同的工作,而且序列号和确认号在每个过程中的变化都是不同的。