TCP序列号和确认号详解

完整的PDF下载:

在网络分析中,读懂TCP序列号和确认号在的变化趋势,可以帮助我们学习TCP协议以及排查通讯故障,如通过查看序列号和确认号可以确定数据传输是否乱序。但我在查阅了当前很多资料后发现,它们大多只简单介绍了TCP通讯的过程,并没有对序列号和确认号进行详细介绍,结合实例的讲解就更没有了。近段时间由于工作的原因,需要对TCP的序列号和确认号进行深入学习,下面便是我学习后的一些知识点总结,希望对TCP序列号和确认号感兴趣的朋友有一定帮助。

1.   序列号和确认号的简介及作用

TCP协议工作在OSI的传输层,是一种可靠的面向连接的数据流协议,TCP之所以可靠,是因为它保证了传送数据包的顺序。顺序是用一个序列号来保证的。响应包内也包括一个序列号,表示接收方准备好这个序列号的包。在TCP传送一个数据包时,它会把这个数据包放入重发队列中,同时启动计时器,如果收到了关于这个包的确认信息,便将此数据包从队列中删除,如果在计时器超时的时候仍然没有收到确认信息,则需要重新发送该数据包。另外,TCP通过数据分段中的序列号来保证所有传输的数据可以按照正常的顺序进行重组,从而保障数据传输的完整。

2.   TCP的通讯过程

在TCP通讯中主要有连接的建立、数据的传输、连接的关闭三个过程!每个过程完成不同的工作,而且序列号和确认号在每个过程中的变化都是不同的。

2.1 TCP建立连接

TCP建立连接,也就是我们常说的三次握手,它需要三步完成。在TCP的三次握手中,发送第一个SYN的一端执行的是主动打开。而接收这个SYN并发回下一个SYN的另一端执行的是被动打开。

这里以客户端向服务器发起连接来说明。

1)   第1步:客户端向服务器发送一个同步数据包请求建立连接,该数据包中,初始序列号(ISN)是客户端随机产生的一个值,确认号是0;

2)   第2步:服务器收到这个同步请求数据包后,会对客户端进行一个同步确认。这个数据包中,序列号(ISN)是服务器随机产生的一个值,确认号是客户端的初始序列号+1;

3)   第3步:客户端收到这个同步确认数据包后,再对服务器进行一个确认。该数据包中,序列号是上一个同步请求数据包中的确认号值,确认号是服务器的初始序列号+1。

注意:因为一个SYN将占用一个序号,所以要加1。

初始序列号(ISN)随时间而变化的,而且不同的操作系统也会有不同的实现方式,所以每个连接的初始序列号是不同的。TCP连接两端会在建立连接时,交互一些信息,如窗口大小、MSS等,以便为接着的数据传输做准备。

RFC793指出ISN可以看作是一个32bit的计数器,每4ms加1,这样选择序号的目的在于防止在网络中被延迟的分组在以后被重复传输,而导致某个连接的一端对它作错误的判断。

2.2 TCP传输数据

在TCP建立连接后,就可以开始传输数据了。TCP工作在全双工模式,它可以同时进行双向数据传输。这里为了简化,我们只谈服务器向客户端发送数据的情况,而客户端向服务器发送数据的原理和它是类似的,这里便不重复说明。
服务器向客户端发送一个数据包后,客户端收到这个数据包后,会向服务器发送一个确认数据包。

传输数据的简要过程如下:

1)   发送数据:服务器向客户端发送一个带有数据的数据包,该数据包中的序列号和确认号与建立连接第三步的数据包中的序列号和确认号相同;

2)   确认收到:客户端收到该数据包,向服务器发送一个确认数据包,该数据包中,序列号是为上一个数据包中的确认号值,而确认号为服务器发送的上一个数据包中的序列号+所该数据包中所带数据的大小。
数据分段中的序列号可以保证所有传输的数据按照正常的次序进行重组,而且通过确认保证数据传输的完整性。

2.3 TCP关闭连接

前面我们提到,建立一个连接需要3个步骤,但是关闭一个连接需要经过4个步骤。因为TCP连接是全双工的工作模式,所以每个方向上需要单独关闭。在TCP关闭连接时,首先关闭的一方(即发送第一个终止数据包的)将执行主动关闭,而另一方(收到这个终止数据包的)再执行被动关闭。

关闭连接的4个步骤如下:

1)   第1步:服务器完成它的数据发送任务后,会主动向客户端发送一个终止数据包,以关闭在这个方向上的TCP连接。该数据包中,序列号为客户端发送的上一个数据包中的确认号值,而确认号为服务器发送的上一个数据包中的序列号+该数据包所带的数据的大小;

2)   第2步:客户端收到服务器发送的终止数据包后,将对服务器发送确认信息,以关闭该方向上的TCP连接。这时的数据包中,序列号为第1步中的确认号值,而确认号为第1步的数据包中的序列号+1;

3)   第3步:同理,客户端完成它的数据发送任务后,就也会向服务器发送一个终止数据包,以关闭在这个方向上的TCP连接,该数据包中,序列号为服务器发送的上一个数据包中的确认号值,而确认号为客户端发送的上一个数据包中的序列号+该数据包所带数据的大小;

4)   第4步:服务器收到客户端发送的终止数据包后,将对客户端发送确认信息,以关闭该方向上的TCP连接。这时在数据包中,序列号为第3步中的确认号值,而确认号为第3步数据包中的序列号+1;

注意:因为FIN和SYN一样,也要占一个序号。理论上服务器在TCP连接关闭时发送的终止数据包中,只有终止位是置1,然后客户端进行确认。但是在实际的TCP实现中,在终止数据包中,确认位和终止位是同时置为1的,确认位置为1表示对最后一次传输的数据进行确认,终止位置为1表示关闭该方向的TCP连接。

3.   实际数据包分析

结合上面的理论,下面我们访问网页来捕获数据包,通过实际的数据包来验证序列号和确认号在TCP连接建立、传输数据以及关闭连接时的变化。

打开科来网络分析系统,首先为减少数据干扰,在过滤器中设置只捕获TCP协议的数据,然后开始捕获,同时,访问,待页面下载完成后,停止捕获。

此次环境中,客户端为192.168.0.92,服务器为:222.77.187.23。

3.1 TCP建立连接

在捕获的数据包中,首先我们来查看建立连接的三次握手信息,并且观察数据包中序列号和确认号的变化。为了让大家看的更加明白,我在这里使用了“添加数据包注释”的功能。

( 建立连接第一步)

客户端向服务器发起一个同步请求数据包,请求连接服务器的80端口,客户端随机产生一个初始序列号(ISN)为2712239078,确认号为0。

注意:在实际情况中,我们访问网站首先进行的是域名解析,这里我们设置了过滤器所以没有捕获到DNS数据包。

( 建立连接第二步)

服务器收到客户的同步请求数据包后,并向客户端发送一个同步确认数据。这个数据包中,服务器随机产生一个初始序列号(1288781508),同时,将客户端发送的初始序列号(ISN)加1(2712239078+1=2712239079)以作为确认号发回给客户段进行确认。

( 建立连接第三步)

客户端收到这个同步确认数据包后,再次对服务器进行一次确认。在这个数据包中,序列号为上一个数据包的确认号(2712239079),确认号为服务器的初始序列号(ISN)加1(1288781508+1=1288781509),以对服务器的同步确认数据包进行确认,这样TCP连接就建立了。

3.2 TCP传输数据

TCP连接建立后,马上就开始传输数据,这里客户端主动向服务器发送一个GET请求,来提交自己的请求信息。

(   传输数据)

图4中的是客户端向服务器发送的GET请求据数据包,我们注意看序列号和确认号的值!该数据包中,序列号为2712239079,确认号为1288781509,这和三次握手的第三步的数据包中的序列号和确认号相同。
从图4中看出这个数据包的大小为1018字节,其中减去14字节Ethernet报头,20字节的IP报头,20字节的TCP报头和4字节的FCS(1018-14-20-20-4=960),得到传输的数据大小为1432。我们将该数据包中的序列号加上该数据大小(即2712239079+960=2712240039),发现与“下一个序列号”的值完全吻合,也就是下一个数据包中服务器发送给客户端的数据包中的确认号。

( 确认收到)

注意:“下一个序列号”是科来网络分析系统为了方便用户查找下一个连续数据包,而根据数据包序列号和确认号自动计算得出,该字段在实际数据包中是不存在的。

3.3 TCP关闭连接

在传输数据完成之后,TCP会关闭连接,这里是服务器主动关闭该方向上的TCP连接。我们继续来观察捕获的数据包,先来看关闭连接的第一步,这里是服务器主动发起关闭

(   关闭连接第一步)

服务器向客户端主动发起确认位和终止位同时置为1的数据包,确认位置1表示对最后一次传输的数据进行确认,终止位置1表示关闭该方向的TCP连接,关闭服务器和客户端的TCP连接。在这个数据包中,序列号为客户端发送的上一个数据包中所带的确认号值(1288781777),而确认号为服务器发送的上一个数据包中的序列号+该数据包所带的数据的大小(2712238597+1432=2712240039);

然后客户端收到该终止数据包,会对服务器发送一个确认数据包,该数据包中,序列号为第1步中的确认号值(2712240039),而确认号为第1步的数据包中的序列号+1(1288781777+1=1288781778);
我们注意观察序列号和确认号的变化情况。

( 关闭连接第二步)

随后,就是来自客户端被动发起的关闭,它与服务器主动发起的关闭同理,只不过这次是被动关闭客户端方向上的TCP连接,我们就不重复说明。

我们根据以上对TCP的建立连接、传输数据和关闭连接三个过程的抓包分析,成功的验证了前面所说的理论。

【转】TCP的SEQ和ACK的生成的更多相关文章

  1. TCP三次握手的seq和ack号的【正确】理解

    1 理论知识 先上一张图,TCP/IP详解第18章的这张图描述了一个正常的三次握手和四次挥手的状态迁移,以及seq.ack序号的变化. 基本状态看图就能了解,本文主要围绕序号的变化进行讲解. 1)se ...

  2. TCP的核心系列 — ACK的处理(一)

    TCP发送数据包后,会收到对端的ACK.通过处理ACK,TCP可以进行拥塞控制和流控制,所以 ACK的处理是TCP的一个重要内容.tcp_ack()用于处理接收到的ACK. 本文主要内容:TCP接收A ...

  3. 一站式学习Wireshark(四):网络性能排查之TCP重传与重复ACK

    作为网络管理员,很多时间必然会耗费在修复慢速服务器和其他终端.但用户感到网络运行缓慢并不意味着就是网络问题. 解决网络性能问题,首先从TCP错误恢复功能(TCP重传与重复ACK)和流控功能说起.之后阐 ...

  4. Seq和Ack

    http://blog.csdn.net/bytebai/article/details/21752925 握手阶段: 序号    方向         seq           ack1  A-& ...

  5. Wireshark(四):网络性能排查之TCP重传与重复ACK

    原文出处: EMC中文支持论坛 作为网络管理员,很多时间必然会耗费在修复慢速服务器和其他终端.但用户感到网络运行缓慢并不意味着就是网络问题. 解决网络性能问题,首先从TCP错误恢复功能(TCP重传与重 ...

  6. [置顶] NS2中对TCP数据包和ACK包的TCP Sink类的主要实现代码详尽剖析--吐血放送

    NS2中对TCP数据包和ACK包的TCP Sink类的主要实现代码详尽剖析,限于个人水平,如有错误请留言指出! TcpSink类的recv()方法: void TcpSink::recv(Packet ...

  7. 反向代理&集线器和交换机的区别&广播地址&seq与ack的区别

    反向代理服务器: 当一个代理服务器能够代理外部主机访问内部网络时,这种代理服务的方式称为反向代理服务,该服务器被称为反向代理服务器. 集线器与交换机的区别: 集线器和交换机都是起到端口转发的作用,不同 ...

  8. TCP三次握手机制中的seq和ack

    TCP连接的三次握手:第一次(A--->B),SYN=1,seq=x第二次(B--->A),SYN=1,ACK=1,seq=y,ack=x+1 第三次(A--->B),ACK=1,s ...

  9. TCP的核心系列 — ACK的处理(二)

    本文主要内容:tcp_ack()中的一些细节,如发送窗口的更新.持续定时器等. 内核版本:3.2.12 Author:zhangskd @ csdn 发送窗口的更新 什么时候需要更新发送窗口呢? (1 ...

随机推荐

  1. 在VS2012下不安装VS2010编译VS2010的工程

    虽然一路追随这VISUAL SUTDIO在编程,但是断档的情况还是有的,最近一次硬盘问题使得安装了所有的VS2003-VS2012的机器硬盘挂了,无奈只能够安装了,不过觉得没啥用了,就安装一个VS20 ...

  2. TreeView节点拖拉操作1

      TreeView节点拖拉操作1 //事先设置 TreeView1.DragMode= dmAutomatic;   unit Unit1; interface uses   Windows, Me ...

  3. PACPerformance

    https://github.com/kickfjq/android_packages_apps_PACPerformance

  4. android拦截短信并屏蔽系统的Notification

    拦截短信有几个关键点: 1.android接收短信时是以广播的方式 2.程序只要在自己的Manifest.xml里加有"接收"SMS的权限 <uses-permission  ...

  5. fscanf()函数具体解释

    曾经解析有规律的文件的时候要么用正則表達式,要么就是傻傻的自己敲代码来解析有规律的文件.今天突然发现c的库函数中有一个现成的能够解析有规律的文件的函数,就是fscanf()函数.哎 曾经自己做了这么多 ...

  6. phonegap 安装和使用eclipse

    1.下载nodejs...然后注销让nodejs可用 2.下载jdk,ant.和安卓的sdk. jdk是为ant编译时需要,设置JAVA_HOME环境变量 C:\Program Files\Java\ ...

  7. c语言例子递归与整数逆序

    例一 #include <stdio.h> //将一整数逆序后放入一数组中(要求递归实现) void convert(int *result, int n) { if(n>=10) ...

  8. SQL中空值与NULL区别

    很多人都有过这样的问题吧   在SQL中填充空值与NULL有什么区别 现在我以一个实例给大家分享一下自己的想法  恳请大家给予批评也指正 谢谢 创建一个监时表 CREATE TABLE #temp ( ...

  9. Android(java)学习笔记96:如何改变spinner系统自带的字体和颜色

    1.首先我们要知道spinner系统自带字体和颜色本质: 原生的Spring 控件是无法更改字体和颜色的... 从下面的代码可以看出...红色的标注显示使用的是Android默认的布局.. Spinn ...

  10. div 并排

    <style type="text/css">#d1 {float:left;background:#f00;}#d2 {float:left;background:# ...