TCP包头和封装

TCP包头尺寸除非存在选项,否则其正常大小为20字节。

1.源端口

  • 源端口是一个16位字段。
  • 它标识发送应用程序的端口。

2.目的端口

  • 目标端口是一个16位字段。
  • 它标识接收应用程序的端口。

注意重要的是要注意-TCP连接是通过以下方式唯一标识的:发送方和接收方的端口号和IP地址的组合IP地址指示正在通信的系统。端口号指示哪个端对端套接字正在通信。

3. 序列号(Sequence Number

  • 序列号是一个32位字段。
  • TCP为TCP段中包含的每个数据字节分配一个唯一的序列号。
  • 该字段包含第一个数据字节的序列号。

序列号(Sequence Number)字段包含了TCP从发送端发送刀接收端时此数据报文开始的第一个字节。 考虑如下场景,源端应用发送TCP数据流到目标端应用时,TCP就会为此数据流里面的每一个字节标注一个序列号,此序列号是一个32位无符号数字,在达到(2 32)− 1 后回绕为0。

此处要注意区分TCP数据包上的序列号字段和刚刚说的序列号,TCP每一个字节都存在他特定的序列号,但是TCP在传输过程中并不会传输此数据报文的所有序列号,而是只在TCP包头的序列号字段处打上此报文的第一个字节对应的序列号,因为这样已经足够满足TCP发送方和接收方之间的协商确认流程。

回到主题,由于TCP数据流的每个字节都已编号,因此接受者接收到TCP数据包以后,就可以轻松的知发送者希望接收的下一个序列号,计算方法如下:

当前接收到的报文序列号 + 当前报文负载总长度 + 1 = ACK 确认编号

确认号(Acknowledgement Number)

  • 确认号是一个32位字段。
  • 它包含接收者期望接下来从发送者接收的数据字节的序列号。
  • 它总是最后一个接收到的数据字节的序列号加1。

确认号(Acknowledgement Number)通过TCP的“ 确认编号”字段(也称为ACK编号ACK)字段(简称字段),接收者向发送者确认收到对应的数据包。

通常适用于除TCP会话初始和TCP会话结束部分以外的所有部分。发送ACK并不会引入额外开销,因为它是与与TCP其他任意数据包一起发送,因为32位ACK Number字段始终是报头的一部分,而每一个TCP数据包都存在包头。

建立新连接后,在从客户端发送到服务器的第一段中,SYN字段将被标识。

然后,在该TCP发送方向上(请注意,连接都是双向的),序列号字段包含此TCP方向的第一个初始序列号。

注意,此数字不是 0或1,而是一个随机数,称为初始序列号(ISN)。ISN不为0或1的原因是一种安全措施。

在此连接方向上发送的数据的第一个字节的序列号是ISN + 1,因为SYN位字段消耗一个序列号。

正如我们将在后面看到的,使用序列号也意味着使用重传进行可靠的传递。

因此,SYN和之后的TCP流量,以及FIN因为有了序列号的加持下被可靠地传递。

而不消耗序列号的ACK则没有可靠性保障,例如你不会发送一个ACK去确认一个ACK,如此将会无限循环。

当然,这里也会引入一个问题,ACK丢了怎么办,毕竟发送ACK的一端并不知道对端是否已经收到这个ACK,而最后的结果是,发送数据包的一方(注意不是发送ACK的一方,因为ACK是由接收到数据的一方发出来)会做数据包重传。

5.包头长度(Header Length)

  • 包头长度是一个4位字段。
  • 它包含TCP包头的长度。
  • 它有助于了解实际数据从何处开始。

最小和最大标题长度

TCP包头的长度始终在以下范围内:[20字节,60字节]

  • 始终使用TCP包头的前5行。
  • 因此,TCP包头的最小长度= 5 x 4字节= 20字节。
  • 代表“选项”字段的第六行的大小有所不同。
  • 选项字段的大小最多可以为40个字节。
  • 因此,TCP头的最大长度= 20字节+ 40字节= 60字节。

比例因子的概念

  • 包头长度是一个4位字段。
  • 因此,可以表示的十进制值的范围是[0,15]。
  • 但是标题长度的范围是[20,60]。
  • 因此,为了表示包头长度,我们使用4的缩放因子。

一般来说:
包头长度=包头长度字段值x 4字节

例子

  • 如果包头长度字段包含十进制值5(表示为0101),则:

包头长度= 5 x 4 = 20字节

  • 如果包头长度字段包含十进制值10(表示为1010),则:

包头长度= 10 x 4 = 40个字节

  • 如果包头长度字段包含十进制值15(表示为1111),则:

包头长度= 15 x 4 = 60字节

笔记

重要的是,要注意包头长度包头长度字段值是两个不同的东西。

包头长度字段值的范围始终为[5,15],而包头长度的范围始终为[20,60]。

当讨论到TCP的头长度的时候,如果给出的头长度是在[5,15]范围内,则为包头长度字段值。

反之如果给出的值是在20 <-> 60之间,则是TCP的数据包头长度值,因为其的范围始终为[20,60]。

6.保留位

  • 6位保留。
  • 这些位未使用。

7. URG位

URG位用于紧急处理某些数据。

当URG位置1时

  • 它指示接收器当前段中的一定数量的数据很紧急。
  • 通过评估紧急指针字段来指出紧急数据。
  • 紧急数据已被优先处理。
  • 接收方在单独的通道上将紧急数据转发到接收应用程序。

8. ACK位

ACK位指示确认号字段是否有效。

  • 当ACK位设置为1时,表示TCP头中包含的确认号有效。
  • 对于除请求段以外的所有TCP段,ACK位都设置为1。
  • 在三向握手期间发送请求段以建立连接。

9. PSH位

PSH位用于将整个缓冲区立即推送到接收应用程序。

当PSH位设置为1时,

  • 缓冲区中的所有段将立即推送到接收应用程序。
  • 无需等待填充整个缓冲区。
  • 这使整个缓冲区立即释放。

注意重要的是要注意-与URG位不同,PSH位不对数据进行优先级排序。它只是使缓冲区中的所有段立即被推送到接收应用程序。分段到达的顺序保持不变。将PSH位设置为1.不是一个好习惯。这是因为它破坏了接收器CPU的工作,并迫使其立即采取措施。

10. RST位

RST位用于重置TCP连接。

当RST位置1,

  • 它指示接收器立即终止连接。
  • 这会导致双方异常释放连接及其所有资源。
  • 数据的传送在两个方向上均停止。
  • 这可能会导致传输中的数据丢失。

仅在以下情况下使用此选项:

  • 存在不可恢复的错误。
  • 没有机会正常终止TCP连接。

11. SYN位

SYN位用于同步序列号。

当SYN位置1,

  • 它指示接收方TCP头中包含的序列号是初始序列号。
  • 在三向握手期间发送的用于建立连接的请求段的SYN位设置为1。

12. FIN位

FIN位用于终止TCP连接。

当FIN位置1,

  • 它指示接收者发送者要终止连接。
  • 发送用于TCP连接终止的 FIN段 包含FIN位设置为1。

13.窗口大小

  • 窗口大小是一个16位字段。
  • 它包含发送方接收窗口的大小。
  • 它通告发送者无需确认即可接收多少数据(以字节为单位)。
  • 因此,窗口大小用于Flow Control。

注意重要的是要注意-窗口大小在数据传输期间动态变化。在TCP传输期间,它通常会增加到检测到拥塞的程度。在检测到拥塞之后,将减小窗口大小以避免丢失数据包。

14.校验和

  • 校验和是用于错误控制的16位字段。
  • 它验证TCP有效负载中数据的完整性。
  • 发送方在发送数据之前将CRC校验和添加到校验和字段。
  • 接收方拒绝未通过CRC检查的数据。

15.紧急指针

  • 紧急指针是一个16位字段。
  • 它指示从第一个数据字节开始计数的当前段中有多少数据是紧急数据。
  • 添加到序列号的紧急指针指示紧急数据字节的结尾。
  • 仅当URG位设置为1时,此字段才被视为有效且已评估。

有用的配方 Formula-01:紧急字节数=紧急指针+ 1 公式02:紧急字节结尾=段中第一个字节的序列号+紧急指针

16. TCP选项

  • 选项字段用于多种目的。
  • 选项字段的大小从0字节到40字节不等。

选项字段通常用于以下目的:

  1. 时间戳记
  2. 窗口尺寸扩展
  3. 参数协商
  4. 填充

A.时间戳

当回绕时间小于段的生存时间时,

  • 具有相同序列号的多个片段可能会出现在接收方。
  • 这使得接收机难以识别正确的片段。
  • 如果使用时间戳,则标记TCP段的年龄。
  • 根据时间戳,接收方可以识别正确的段。

B.窗口尺寸扩展

  • 选项字段可用于表示大于16位的窗口大小。
  • 使用TCP头的窗口大小字段,只能表示16位的窗口大小。
  • 如果接收方希望接收更多数据,则可以使用此字段来通告其更大的窗口大小。
  • 然后,多余的位将附加在“选项”字段中。

C.参数协商

选项字段用于参数协商。

示例-建立连接期间,

  • 发送方和接收方都必须指定其最大段大小。
  • 要指定最大段大小,没有特殊字段。
  • 因此,他们使用此字段指定最大段大小并进行协商。

D.填充

  • 添加伪数据以填充传输单元中未使用的空间并使其符合标准大小称为填充。
  • 选项字段用于填充。

  • 如果标题长度不是4的倍数,则在“选项”字段中填充额外的零。
  • 这样,包头长度将变成4的倍数。
  • 如果标题长度= 30个字节,则将2个字节的伪数据添加到标题中。
  • 这使包头长度= 32个字节。
  • 然后,将值32/4 = 8放入包头长度字段。
  • 在最坏的情况下,可能必须填充3个字节的伪数据以使包头长度为4的倍数。

觉得文章有用?

点个广告表达一下你的爱意吧 !😁