逻辑结构
如图,每个字段的大小以及位置分布(图中有许多信息,请仔细阅读):
从图中我们可以看出,TCP段的大小不是固定的,它会因为可选选项或者需要传输的数据的大小而变化。
TCP段实际上是和UDP数据包一样是条带状的。每个字段的实际排列顺序根据上图,依次是源端口、目的端口、序号、确认序号…(从左到右,从上到下)。如图:
字段解析
一、源端口&目的端口
-
表示范围:
这两个字段分别占用16个比特位,也就是2个字节。刚好契合端口号的范围,不浪费存储空间(0~65535,即216-1)。 -
作用:
两个字段的功能和UDP中的一样,标识发送端以及接收端中实际操作的进程。
二、序号&确认序号
-
表示范围:
序号和确认序号分别占用32个比特位,也就是4个字节。大小在0~ 4,294,967,295(即0~232-1)。 -
作用:
-
序号:
如图,传输层传输数据给IP层会经历这个阶段:
接收端因为要接收多个这种TCP段,而因为网络传输的不稳定性,到达的TCP段可能是缺失的乱序的,甚至因为重传机制还可能发送重复的TCP段给到接收端。为了避免这种情况引入了序号 这个字段。它对每一个TCP段进行标记,每个正在发送的TCP段都有唯一的序号,这样接收端就可以根据序号 对TCP段进行查重、查缺、排序等操作了。 -
确认序号:
TCP是可靠传输这个众人皆知。所谓的可靠传输通俗讲就是,接收端一直没有首到数据,发送端就一直发送数据给接收端,知道接收端拿到数据。
那么发送端是如何知道接收端没有拿到对应的数据呢?靠的就是确认序号:
-
图片说明:
- 数据包中含有TCP段,确认序号是87表示发送端告诉接收端: 你发送的86号以及之前的ACK我都接收到了,期待你发送87以及之后序列号的ACK。
- ACK中 确认序号为102表示接收端告诉发送端: 你发送的序列号为101以及之前序列号的数据包我都已经接收到了,我期待你下一次发送102以及之后序列号的数据包给我。
注意:
序号的增长不是加1线性递增的,它是按照发送TCP段的字节大小递增的:
- 注意事项:
有些小伙伴可能会有这样的疑问:
序号以及确认序号的可表示范围不是有限的吗,在数据传输时,如果TCP段过多,或者TCP段数据过大,超出它们的可表示范围怎么办?
根据协议要求,会直接循环回到0开始重新用。
如果重复环绕使用序号,有没有可能出现两个不同的TCP段,但是序号是相同的?
这实际上也不可能存在,因为序号的大小是0~232-1,但是在数据发送是TCP段的发送量会受到滑动窗口这个机制的影响,而滑动窗口的大小一般最大就是216-1。如果要环绕序号存在两个不同的TCP段,但是它们的序号一样,那么TCP滑动窗口的大小至少也得是232。 但在考虑最极端的使用窗口大小因子,窗口大小也只能是(216-1)x214远远小于232-1。
三、头部长度
-
表示范围:
这个字段大小是4位,单位是4字节。
例如,头部长度为5,那么表示该TCP段头部长度是4x5=20个字节。
头部长度值的范围只能在[5,15]。 -
作用:
头部长度,也叫数据偏移(Data Offset),我们知道TCP段头部长度是可变的,通过这个字段就可以知道该TCP段头部的具体是在那个范围了。
注意:
在传输层,TCP段的起始位置不用管,只用知道偏移量(头部长度)即可,起始位置在IP层有专门字段封装。
四、保留位
- 表示范围: 保留位大小是三位。
- 作用:
它的出现是吸取了UDP的教训,UDP由于报文结构被写死,导致后续数据传输量受到限制,很难进行更改。而TCP引入保留位,就是为将来可能的扩展提供位置。因此当下保留位没有确切的功能,或者说功能就是为将来做扩展搞得一个“备胎”。
五、特殊标志位
TCP段中,九个标志位,每个表示为都只占用一个比特位。这些标志位相当于信号枪,如果被置为1,就代表什么事情发生了。小编将会按照TCP段从左到右的顺序依次讲解:
NS(Nonce Sum)
- 作用:与显式拥塞控制(ECN)扩展功能相关,用于保护ECN功能,防止拥塞窗口被恶意缩减。
CWR(Congestion Window Reduced)
- 作用:由发送端设置,用来通知接收端它已经收到ECE标志,并且已经减小了发送窗口,以应对网络拥塞。
ECE(ECN-Echo)
- 作用:表示接收端已经接收到带有ECN标志的包,并将此信息传回发送端。在ECN(Explicit Congestion Notification)机制中使用。
- URG(Urgent Pointer field significant)
- 作用:表明本段中存在需要优先处理的紧急数据。当URG标志位被设置时,TCP头部的紧急指针(Urgent Pointer)字段被认为是有效的。
- ACK(Acknowledgment field significant)
- 作用:表示确认号(Acknowledgment Number)字段的有效性。几乎所有的TCP段都会设置这个标志位,用于确认已经接收到的数据。
- PSH(Push Function)
- 作用:提示接收端应用层应立即处理接收到的数据,而不是将其缓存。用于实时通信场景。
- RST(Reset the connection)
- 作用:表示连接被重置。当接收到一个设置了RST标志位的段时,TCP连接会被立即关闭,所有未完成的数据传输都会被丢弃。
- SYN(Synchronize sequence numbers)
- 作用:用于同步序列号,在建立TCP连接时用于初始化序列号。SYN段是TCP三次握手过程中使用的,标志着一个连接的开始。
- FIN(No more data from sender)
- 作用:表示发送端已经完成了数据传输,要求终止连接。用于TCP连接的正常关闭。
注意:
前三个标志位都是用来支持TCP中的显式拥塞机制(ECN)的,关于这个机制的具体作用以及运作流程请移步:显示拥塞控制(ECN)
六、窗口大小
- 表示范围: 占用2个字节,所以表示范围在0~65535。
- 作用:
窗口大小描述的是接收方可接收数据的多少。如果接收端现在可以接收大量数据那么窗口大小就可以填一个很大的值,反之亦然。窗口大小本质其实就是接收端接收缓冲区大小。换句话说,它是服务于流量控制的。关于接收窗口或者流量控制机制,详细请观看:TCP流量控制与拥塞控制详解 - 窗口缩放因子:
刚才我们讲到,窗口的大小范围在0~65535。
这个大小一般够用,但有些特殊情况,还需要把窗口扩大一下。这时窗口缩放因子就排上了用场。窗口缩放因子是选项这个字段中的一种选项。TCP规定窗口缩放因子的值只能在0~14。
窗口实际大小=
窗口原来大小x
2窗口缩放因子
七、校验和
- 范围: 占用TCP段两个字节,所以范围在0~65535。
- 作用: 校验和用于检验数据传输过程是否出现错误。校验和首先在数据发送前根据正确的数据计算得到,然后在接收端接收,根据接收收到的数据在次计算验证,如果不相等视为这个数据包出错了。
- 注意事项:
UDP和TCP校验和功能和计算方式基本一样,采用1的补码求和,这种计算发送很可能产生溢出,这个是不要紧,因为校验和要求的是数据计算结果是否一致,而不在乎计算是否"正确"。关于具体计算方法,请移步:UDP数据包结构剖析
八、紧急指针
- 表示范围:
占用两个字节,所以表示范围在0~65535。 - 作用:
紧急指针仅当URG标志位设置时生效。如果当前TCP段中有紧急的数据需要处理,那么就可以把URG标志位设置成1。紧急指针就相当于紧急数据的偏移量(序号作为起始位置),代表紧急数据的范围。TCP段到达接收端,会优先处理这个紧急数据,快速把它发送到应用层,而不必排队。紧急指针现在用的并不广泛,一般采用其他机制来处理优先级高的数据。
九、可选选项
-
表示范围: 占用0~40个字节不等。
-
作用:
可选字段是用于扩展TCP功能的一部分,允许在不改变基本TCP头部结构的情况下添加新的功能或改进现有功能。
以下是常见的TCP可选选项及其功能(了解即可,不用掌握):-
最大段大小(MSS, Maximum Segment Size)
- 功能:指定连接中可以发送的最大TCP段中数据字段的大小(不包括TCP头部和IP头部)。MSS通常是在TCP连接建立时协商的,发送方使用MSS来告诉对方它期望接收的最大段大小。
- 用途:通过MSS,双方可以避免发送超过接收方网络条件允许的段大小,从而减少分片,提高传输效率。
- 默认值:MSS的默认值通常为536字节,但可以根据网络条件协商更大的值,如1460字节(以太网标准MTU为1500字节)。
-
窗口缩放因子(Window Scale Option)
- 详细内容在第六个标题讲了,这里不过多赘述。
-
时间戳选项(Timestamps Option)
- 功能:提供发送时间戳和回送时间戳,用于计算往返时间(RTT)和提高TCP的拥塞控制机制。这是通过两个32位字段来实现的:一个用于发送方的时间戳值,另一个用于接收方的回送时间戳回值。
- 用途:时间戳选项有助于实现精确的RTT估算,有助于更好的拥塞控制和避免序号回绕问题(序号空间重复)。
-
选择性确认(SACK, Selective Acknowledgment)
- 功能:允许接收方选择性地确认收到的TCP段,而不是累积确认,从而使发送方只需重传那些丢失的数据段。这是通过SACK选项中的一系列“块”来表示哪些数据段已成功接收。
- 用途:SACK提高了TCP在丢包环境中的效率,减少了不必要的重传,特别是在高丢包率的网络中。
-
NOP选项(No Operation Option)
- 功能:用于在TCP选项字段中填充空间,使选项字段长度对齐为4字节的倍数。
- 用途:NOP选项没有实际的功能,但它用于调整选项字段的长度,以确保符合TCP头部的长度要求。
-
快速打开(TCP Fast Open)
- 功能:允许在TCP三次握手过程中携带数据,从而减少连接建立的延迟。通过在初次连接时交换的“cookie”,后续连接可以跳过部分握手步骤,并在握手阶段同时发送数据。
- 用途:适用于需要快速建立连接的应用场景,例如Web服务,提高初次连接的数据传输效率。
-
选择性确认许可(SACK-Permitted Option)
- 功能:在TCP连接的建立过程中,发送方可以使用该选项告知对方它支持选择性确认(SACK)功能。
- 用途:用于协商双方是否支持SACK功能,这通常出现在三次握手中的SYN段中。
-
十、数据
- 范围:
这个字段是可有可无。例如传输ACK时,就不存在这个字段。如果需要传输实际数据就必须存在。
至于它的最大值,TCP协议没有明确规定,但是实际情况会受到其他协议层制约,最大值大概是1500个字节左右。 - 作用:
存储实际需要发送的数据。