前言
上篇讲解了UDP报文格式。TCP和UDP是同层协议,都属于传输层,数据来源于上层——应用层
目录
一. TCP协议概述
二. TCP报文格式
1. 两个问题
2. 确认号和序列号
3. 标志位字段
4. 窗口大小
5. 校验和字段
6. 紧急指针与紧急数据
7. 选项字段
结束语
一. TCP协议概述
TCP——传输控制协议(Transmission Control Protocol)。是一种面向连接的,可靠的,基于字节流的传输层通信协议
TCP旨在适应支持多网络应用的分层协议层次结构。连接到不同但互连的计算机通信网络的主计算机中的成对进程之间依靠TCP提供可靠的通信服务。TCP假设它可以从较低级别的协议获得简单的,可能不可靠的数据报服务。原则上,TCP应该能够在从硬线连接到分组交换或电路交换网络的各种通信系统支行操作
二. TCP报文格式
图中的数字单位是bit(比特位),32位代表32个bit——4字节
我们先粗略的了解TCP报文格式
TCP报文由如下部分组成:
1. 端口号
16位源端口:发送方主机的应用程序的端口号
16位目的端口:目的主机的应用程序的端口号
2. 序列号
32位CP序列号:表示本报文段所发送数据的第一个字节的编号
3. 确认号
32位TCP确认序号:表示接收方期望收到发送当下一个报文段的第一个字节数据的编号
4. 首部长度
4位TCP首部长度:数据偏移是指数据段中的“数据”部分起始处距离TCP报文段起始处的字节偏移量。确定TCP报文的报头部分长度,告诉接收端应用程序,数据(有效载荷)从何处开始
5. 保留字段
6位保留字段:为TCP将来的发展预留空间,目前必须全部为0
6. 标志位字段
6位标志位:共有6个标志位,每个标志位占1个bit
7. 窗口大小
16位窗口大小:表示发送该TCP报文的接受窗口还可以接受多少字节的数据量。该字段用于TCP的流量控制
8. 校验和
16位校验和字段:用于确认传输的数据有无损坏 。发送端基于数据内容校验生成一个数值,接收端根据接受的数据校验生成一个值。两个值相同代表数据有效,反之无效,丢弃该数据包。校验和根据 伪报头 + TCP头 + TCP数据 三部分进行计算
9.紧急指针
16位紧急指针字段: 仅当标志位字段的URG标志位为1时才有意义。指出有效载荷中为紧急数据的字节数。当所有紧急数据处理完后,TCP就会告诉应用程序恢复到正常操作。即使接收方窗口大小为0,也可以发送紧急数据,因为紧急数据无须缓存
10. 选项字段
选项字段:长度不定,但长度必须是32bits的整数倍。内容可变,因此必须使用首部长度来区分选项的具体长度
接下来详细理解每个字段的作用
1. 两个问题
每层协议的学习,我们都应该掌握这两个问题:
- 协议报头和有效载荷如何分离?
- 有效载荷如何向上交付?
第一个问题,协议报头和有效载荷如何分离。
我们看到,TCP首部包括20字节的固定长度首部和选项字段,同时固定首部中有一个首部长度字段(4bits)。
通过首部长度字段,我们可以知道TCP首部的长度,其单位为4字节。首部长度最大可表示15,即TCP首部最长为15 x 4 =60字节。因为固定首部20字节,所以选项字段最长40字节。当没有选项字段时,首部长度字段为5(20 = 5*4),即0101。
通过首部长度,我们就可以将TCP首部和有效载荷分离。
第二个问题,有效载荷如何向上交付。
TCP是传输层的,上层是应用层。而应用层程序会绑定端口号,TCP首部中有16位目的端口号,根据端口号做到向上交付。
2. 确认号和序列号
TCP协议属于传输层,和IP层一起由操作系统管理。TCP在操作系统重有自己的缓冲区
在网络通信中,应用层调用的write,sendto等接口,只是将我们自己定义的缓冲区数据拷贝到TCP的发送缓冲区。而TCP是面向字节流的。在TCP缓冲区中,以字节为单位,将缓冲区划分成了类似字符数组的形式,数组自带下标,所以TCP缓冲区的每个字节就有编号
序列号和确认号就是TCP缓冲区的编号(下标)
- 序列号:表示本报文第一个字节的编号(在缓冲区的下标)。在TCP连接中,所传输的字节流的每一个字节都会按顺序编号
- 确认号:在客户服务器模式中,当发送方给接收方发送数据,接收方只要接收到数据,必须给发送方发送确认报文。此时报文中的确认号,表示接收方期望收到发送方下一个报文的第一个字节的编号。确认号通常和序列号搭配使用。如下图
- 主机A给主机B发送消息:序列号123,即该报文第一个字节的编号为123。该报文长度77。确认号,期望主机B发送首字节编号为100的报文。
- 主机B收到主机A的消息,发送确认报文:序列号,即该报文第一个字节的编号为100。根据主机A发送的确认号而定。该报文长度50。确认号,期望主机A下一次发送201编号的数据,因为主机A先前发送的是123,报文长度为77,即报文范围123~200,下一个要发送的是201。
- 主机A收到主机B的消息,发送确认报文:序列号,201,根据主机B确认报文的确认号而定;该报文长度69。确认号,主机B上一个报文序列号为100,长度50,即下一个即将发送的报文首字节编号为151。所以主机A给主机B的确认号为151
- 以此类推.......
以上通信还涉及两个知识点:确认应答和捎带应答。属于可靠性策略和效率策略,详细可参看:【计算机网络】可靠性策略&效率策略
3. 标志位字段
标志位字段共6bit,有6个标志位,每个标志位1bit,即只有0和1两种状态。
下述标志位涉及TCP的连接管理,三次握手。详细可参看:【计算机网络】连接管理(三次握手,四次挥手)
名称 | 说明 |
URG | 表示本报文中发送的数据(有效载荷)是否包含紧急数据:URG=1时表示有紧急数据;当URG=1时,后续的16位紧急指针字段才有效 |
ACK | 表示本报文前面的确认号字段是否有效:只有当ACK=1时,前面的确认号字段才有效;TCP规定,建立连接后,ACK必须为1 |
PSH | 告诉对方收到该报文段后,上层应用程序立即把数据从TCP接收缓冲区读取,保证TCP接收缓冲区有能力接收新数据或清空TCP接收缓冲区 |
RST | 表示是否重置连接:若RST=1,说明TCP连接出现严重错误(如主机崩溃),必须释放连接,重新建立连接。携带RST标识的报文称为复位报文段 |
SYN | 在建立连接时使用,用来同步序号;当SYN=1,ACK=0时,表示该报文为请求建立连接的报文;当SYN=1,ACK=1时,表示同意建立连接;只有在建立连接的前两次请求中SYN才为1。该报文称为同步报文段 |
FIN | 标记数据是否发送完毕:若FIN=1,表示数据已经发送完毕,可以释放连接。该报文称为结束报文段 |
4. 窗口大小
该字段表示发送该报文的一方的接收缓冲区的接收能力,告知另一方自己的接收能力,提高通信效率。涉及TCP的流量控制。详细参看:【计算机网络】可靠性策略&效率策略
5. 校验和字段
TCP报头检验和用于检验报文的完整性,用于验证TCP报文在传输过程中是否发送错误或者篡改。
校验和是通过对TCP报文的各个字段进行校验和计算得到的一个数值。发送端在发送数据时,会计算TCP报头的校验和,并将该数值填充到校验和字段。接收方在接收数据时,也会对接收到的TCP报文的校验和进行重新计算,并将计算得到的校验和报文中的校验和进行比较。如果两者不一致,就说明报文在传输过程中发送了错误
6. 紧急指针与紧急数据
紧急指针与紧急数据用于处理紧急情况下的数据传输。发送方发送TCP数据时,可以将部分数据标记为紧急数据。这些数据通常具有更高的优先级,接收方在接收到紧急数据时需要立即处理,而不是按照正常顺序处理。
- 紧急指针
紧急指针用于指示紧急数据的位置。紧急指针是相对于有效载荷序列号字段的偏移量,如果紧急指针的值非0,为X,表示从有效载荷开始第X字节后的数据被标记为紧急数据。
接收方在接收到带有紧急指针的TCP报文时,会立即处理紧急数据,并告知上层应用程序有紧急数据到达。
- 紧急数据
紧急数据的长度可以是任意的,取决于发送方在发送数据时指定的长度
紧急数据的长度和紧急指针的值需要再发送方和接收方之间协商一致。发送方和接收方必须通过应用层的约定或者协议规范来确定紧急数据的长度和处理方式。
7. 选项字段
TCP首部结构的最后一个选项(Options)字段是一个变长的可选信息,它提供了一些额外的功能或对TCP协议进行扩展。TCP选项字段通常包含一个选项类型,一个长度字段和一个选项值
根据首部长度,算出选项字段的最大长度是40字节。典型的选项字段的结构示意图如下:
- kind:占1字节。该字段是说明选项的类型。有的TCP选项没有后面两个字段,仅包含1字节的kind字段
- length:占1字节。指定该选项的总长度。该长度包括kind字段和length字段占据的2个字节
- info:选项的具体信息。常见的TCP选项有7种,如下图
- kind=0:选项表结束选项
- kind=1:空操作(nop)选项,没有特殊含义,一般用于将TCP选项的总长度填充成4字节的整数倍
- kind=2:最大报文段长度(Maximum Segment Size,MSS)选项。MSS是每个TCP报文段中的数据部分的最大长度。数据部分加上TCP首部才等于整个TCP报文段。在建立TCP连接的过程中,双方把自己能够支持的MSS填入这一字段,以后就按照这个数值传输数据,提高效率,网络利用率。双方可以有不同的MSS值。若主机未填写这一项,则MSS的默认值为536字节长度。因此,所有互联网上的主机都应能接受报文长度为536+20(TCP固定首部长度) =586字节
- kind=3:窗口扩大因子选项。(1) 该选项是为了扩大窗口的,上图中,窗口扩大选项占3字节,其中一个字节为移位数M。假设TCP首部中的接收窗口字段值为N,移位值为M,那么TCP报文段的实际接收窗口大小为:N*2^M。M的取范围是[0,14]的整数值。我们可以通过修改Linux系统重的 /proc/sys/ipv4/tcp_window_scaling 内核变量来启动或者关闭窗口扩大因子选项。(2) 和MSS一样,该选项只能出现同步报文段(SYN=1)中,否则将被忽略。但同步报文段本身不执行窗口扩大操作,即同步报文段首部的接收窗口字段就是该TCP报文段的实际接收窗口大小。当TCP连接建立好之后,每个数据传输方向的窗口因子就确定下来了。如果连接一方实现了窗口扩大,当它不需要扩大窗口时,可发送M=0选项,使窗口回到16
- kind=4:选择确认(Selective Acknowledgment,SACK)选项。TCP通信时,如果某个TCP报文段丢失,则TCP模块会重传最后被接收方确认的TCP报文段后续的所有报文段,这样原先已经正确传输的TCP报文段也可能重复发送,从而降低TCP性能。SACK选项正式为了改善这种情况而产生的,它使TCP模块只重新发送丢失的TCP报文段,而不用发送所有未被确认的TCP报文段。选择确认字段用于TCP连接建立时,表示是否支持SACK选项。可通过修改Linux系统的/proc/sys/net/ipv4/tcp_sack内核变量来启动或关闭该选项
- kind=5:是SACK实际工作的选项。该选项的参数告诉发送端,本端已经接收到不连续的数据块,从而让发送端据此检查并重发丢失的数据。每个块边沿(end of block)参数包含一个4字节的序号。其中左边沿表示不连续块的第一个数据字节的序号,而右边沿表示不连续块的最后一个数据字节的下一个字节序号。左右边沿之间的数据就是没有收到的。因为一个块信息占8字节,所有TCP首部选项中实际最多可以包含4个这样的不连续数据块
- kind=6:时间戳选项,占10字节。时间戳有以下两个功能
(1) 用来计算通信双方之间的回路时间(Round Trip Time,PTT)。发送方在发送TCP报文段时把当前时间放入时间戳字段,接收方在确认该报文段时把时间戳字段值复制到时间戳回显应答字段。因此,发送方在收到确认报文后,可以准确地计算出RTT
(2) 用于处理TCP序号超过2^32(4,294,967,296)的情况,这又称为防止序号绕回PAWS(Protect Against Wrapped Sequence numbers)。我们知道,TCP报文段的序号只有32位,而每增加2^32个序号后就会重新从0开始编号。当使用高速网络时,在一次TCP连接的数据传送中序号很可能会被重复使用。例如,当使用 1.5Mbit/s的速率发送TCP报文段时,序号重复要6小时以上。但若使用2.5Gbit/s的速率发送数据报时,则不到14秒钟序号就会重复。为了使接收方能够把新的报文段和迟到很久的报文段(序号相同的情况下)区分开,可以在报文段中加上时间戳选项。我们可以通过修改Linux系统的 /proc/sys/net/ipv4/tcp_timestamps 内核变量来启用和关闭时间戳选项。
并不是所有的TCP实现都支持所有的选项类型。因此,在使用TCP选项字段时需要确保双方都支持相应的选项类型和长度,否则可能会导致通信错误和不兼容问题。
参考文档:https://blog.csdn.net/u010429831/article/details/118702818
结束语
本篇博客到此结束,感谢看到此处。
欢迎大家纠错和补充
如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。