在做TCP链接数据分析时,经常会碰到Seq Number和ACK Number,这两个东西挺困扰人的,后来无意中发现一篇帖子,是讲这个的,我整理一个中文版的出来,便于以后自己忘记的时候能有个地方查查。
使用的抓包工具是wireshark,这应该是个免费的工具,功能方面很强大,如果有兴趣的可以整来研究一下。文章中用到的示例文件在这里(需要安装wireshark工具)
因为文章涉及的是TCP链接方面的内容,所以在看之前,需要有些TCP建立链接时三次握手这些比较基础的知识。
文章中使用了一个例子,是一个单一的对web server的HTTP请求,向服务器请求一个image file,服务器方面会返回一个HTTP/1.1 200(OK)的响应。
先说一下三次握手,TCP头中用到了一些标记位(0或1的值),用以表明连接的状态,最常用的三个是
这三个标记是可以同是被设置的,不过一般来说只同时设置两个,比如ACK+SYN,ACK+FIN
在wireshark中选择第一个包(来自客户端),如下图展开,在Header的Flags内容中可以看到SYN被设置为1
同样的方式来看第二个包(来自服务器),发现ACK和SYN两个都被设置了,这表明服务器端同样希望建立一个TCP连接
第三个包(来自客户端),只有一个ACK标记。这三个包表明TCP建立一个连接时的三次握手最终完成。
下面就开始讲Sequenc Number和Acknowledge Number了
在一个TCP session中,client和server端都会维护一个23bit的数据,这个数据就是sequence number,这个数据被用来跟踪到底有多少数据被发送或者接收了。Sequence number在每一个TCP包中都有,同时,另一端有一个Acknowledge number来通知发送端这些数据确实被接收到了。
当初始化一个连接时,这个sequence number的值是随机的,范围可以是0到4,294,964,295中的任何一个。但是像wireshark这样的包分析工具只会显示一个相对值,也就是实际接收到的数据大小(换言之,就是初始值被当作0,而不是一个随机数了)。这个相对值是相对于初始化的那个随机值,这样更方便与看到有多少数据被成功传送了。
举例来说,还是刚才TCP连接中的第一个包,我们可以看到sequence number是0,但下面实际显示的值是0xF61C6CBE,或者是十进制的4129057982。
wireshark工具可以把包的传送过程用图的方式表现出来,效果如下图
图中每一行代表一个单独的TCP包,用这个图能够更好的理解sequence和acknowledge number的含义。我们一个包一个包来看
Packet #1
TCP session两端的sequence number都是0(相对值),同样,acknowledge number的值也是0,因为此刻,仅仅是client端发送请求,所以两端都还没有收到过数据呢。
Packet #2
Server对client响应,使用的sequence number是0,因为这是它的第一个TCP包,它的相对acknowledge number为1. 1表明收到了来自client的SYN请求。
需要注意的是,尽管client并没有向server发送具体的数据,但是一旦出现了请求SYN或者FIN标记,可以看作是发送了一个字节的数据,所以在这里server的acknowledge number为1,表明收到了来自client的SYN请求。(ACK不会使这些数据加1)
Packet #3
跟第二个包类似,client使用ack number为1来响应来自server的seq number为0。
Packet #4
这是这个连接中第一个带有发送数据的包(HTTP请求)。它的seq number为1(之前只在packet #1中发送过一个SYN),ack number也是1(只收到过来自server的packet#2的SYN),在这个包中,client一共向server发送了725字节长度的数据。
Packet #5
这个包来自server ,因为之前的ack number为1,因为Packet #4中收到了725字节,所以这里ack number更新为726
Packet #6
这个包是对之前HTTP请求的响应,向client一共发送1448字节的数据,因为client的ack number从1变成了1449
Packet #7
因为之前Packet#4中发送了725字节,所以在这里的seq number为726,因为收到了来自server的1448字节,所以ack number从1变到了1449
剩下的包都是重复以上的动作,知道server向client发送数据完毕。在这个过程中,client的seq number一直保持为726,因为这个过程中,client都是向server发送ACK,所以seq number并不会变化。在server端,由于一直在发送数据,所以它的seq number一直在增加,但ack number一直保持726不变。
一直看到最后的Packet #38
当最后一个数据包发送完毕后,client响应整个HTTP,说明没有更多的数据要求,所以发送给server一个FIN标记的packet,在这里client的ack number和#37的肯定是保持一致的。
Packet #39
server收到来自client终止连接的请求(FIN),所以server的ack number会加1,并且同样会发送一个FIN标记的packet给client
packet #40
client最终的seq number为727,ack number加1最终为22952。这时,client和server端都断开连接,并释放各自占用的资源。
最后总结一下,
Sequence Number用来表明一共发送了多少数据
Acknowledge Number用来表明一共接收到了多少数据
SYN和FIN相当与1个字节的数据
ACK不占用字节数