TCP 特征概述

TCP 协议在网络 OSI 参考模型中的第四层——传输层,是一个 面向连接的(connection-oriented)、可靠的(reliable)、字节流式的(byte stream) 传输协议。

  • 面向连接 :在应用 TCP 协议进行通信之前,双方通常需要通过三次握手来建立 TCP 连接,连接建立后才能进行正常的数据传输。但是同时面向连接的特性给 TCP 带来了复杂的 连接管理 以及用于检测连接状态的 存活检测机制 。同时,TCP 提供全双工通信。
  • 可靠性 :TCP 层需要解决来自 IP 层的四种常见传输错误问题,分别是 比特错误 (packet bit errors)、包乱序 (packet reordering)、包重复 (packet duplication)、丢包 (packet drops),TCP要提供可靠的传输,就需要有额外的机制处理这几种错误。TCP 通过使用 确认重传校验和 这三种基本机制来实现可靠传输。因此TCP协议具有超时与重传管理、窗口管理、流量控制、拥塞控制等功能。
  • 字节流式 :应用层发送的数据会在 TCP 的发送端缓存起来,统一分段(例如一个应用层的数据包分成两个TCP包)或者打包(例如多个应用层的数据包打包成一个TCP数据包)发送,到接收端的时候接收端也是直接按照字节流将数据传递给应用层。也就是说,TCP 的数据流是没有边界的 ,这可能导致粘包。作为对比,同样是传输层的协议,UDP 并不会对应用层的数据包进行打包和分片的操作,一般一个应用层的数据包就对应一个 UDP 包。

报头解析

报头格式

报头大小为 20 ~ 60 字节 ,若没有 option ,则为 20 字节。下面对图中各部分进行解析。

  • 源端口和目的端口: 分别用来唯一标识主机和服务器的进程。

    源端口、目的端口、以及源 IP 地址、目的 IP 地址统称为 四元组 ,它唯一的标识了一个 TCP 连接。一个 IP 地址和一个端口号组成 套接字地址 。接收端的 TCP 层根据不同的端口号来将数据包传送给应用层的不同程序,这个过程叫做 解复用 (demultiplex)。相应的发送端会把应用层不同程序的数据映射到不同的端口号,这个过程叫做 复用 (multiplex)。

  • 序列号(SN): TCP 为待发送缓冲区中的数据编号,与 ARQ 协议不同,此处是为每个字节进行编号,而不是为段进行编号 。序列号范围为 0 ~ 2^{32}-1

    连接时,TCP 在范围内生成一个 随机数 作为 初始序号(ISN) ,那么第一个字节的序号应为 ISN + 1 。例如,ISN = 23 ,第一个分组大小为 500,则其序号为 24 ~ 500 ,那么下一个分组就需要从 501 开始编号。当 SYN =1 时,该序列号有效。TCP 通过序列号来判断丢包,重复和失序。

  • 确认号(ACK): 当 ACK 位为 1 时,该确认号有效。接收方通过使用确认号来告知发送方已收到的字节数(或下一次想收到的字节),比如,接收方收到 SN = 54 的分组,然后回复 ACK = 55 的分组来告知发送方我已收到 55 之前的字节(或下一次我想收到 55 开头的字节流)。与 GBN 相同,确认号时累积的。

  • 头部长度: 表示报头总大小。注意,头部长度仅占 4 bit ,范围为 0 ~ 15 ,而报头大小为 20 ~ 60 bytes,所以头部长度的单位是 4 bytes,也就是说,若头部长度为 11,则报头总大小为 11 × 4 = 44 bytes 。

  • 保留: 占 6 位,这些位必须是0。为了将来定义新的用途所保留,其中 RFC3540 将保留字段中的最后一位定义为 Nonce 标志,用于处理拥塞。

  • 窗口大小: 16 位,表明接收端窗口的空闲空间大小,最大的窗口大小为64Kb 。这个值通常被称为 rwnd 。注意,它也可以表示为对方必须维持的窗口大小 ,因为发送方必须服从接收方的支配。用于流量控制。

  • 校验和: 发送端基于数据内容计算一个数值,接收端要与发送端数值结果完全一样,才能证明数据的有效性。接收端 checksum 校验失败的时候会直接丢掉这个数据包。CheckSum 是根据 伪头部+TCP头+TCP数据 三部分进行计算的。

    伪首部只参与校验,不占空间,不参与传输 。UDP 伪头部 = 源 IP 地址 + 目的 IP 地址 + 8位协议 + 16位UDP长度 。
    UDP 发送方可以选择不计算校验和,而 TCP 必须计算校验和 。UDP 伪首部目的是让UDP两次检查数据是否已经正确到达目的地:第一次,通过伪首部的IP地址检验,UDP可以确认该数据报是不是发送给本机IP地址的;第二,通过伪首部的协议字段检验,UDP可以确认IP有没有把不应该传给UDP而应该传给别的高层的数据报传给了UDP。相较于链路层的 CRC 校验,TCP/UDP 校验和提供相对较弱的差错保护。

  • 紧急指针: 16位,指向优先数据的字节,在URG标志设置了时才有效。如果URG标志没有被设置,紧急域作为填充

  • 标志位:

    • CWR(Congestion Window Reduce) :拥塞窗口减少标志被发送主机设置,用来表明它接收到了设置ECE标志的TCP包,发送端通过降低发送窗口的大小来降低发送速率
    • ECE(ECN Echo) :ECN 响应标志被用来在 TCP 3次握手时表明一个 TCP 端是具备 ECN 功能的,并且表明接收到的TCP包的IP头部的ECN被设置为11。ECN(Explicit Congestion Notification)是一种由网络层辅助的拥塞控制方法,用于显式通知终端拥塞的发生。参考此处
    • URG(Urgent) :该标志位置位表示紧急(The urgent pointer) 标志有效。该标志位目前已经很少使用。
    • ACK(Acknowledgment):取值 1 代表 ACK 字段有效,这是一个确认包,取值0则不是确认包。
    • PSH(Push) :该标志置位时,一般是表示发送端缓存中已经没有待发送的数据,接收端不将该数据进行队列处理,而是尽可能快将数据转由应用处理。在处理 telnet 或 rlogin 等交互模式的连接时,该标志总是置位的。
    • RST(Reset) :用于复位相应的TCP连接。通常在发生异常或者错误的时候会触发复位 TCP 连接,这可能导致数据丢失。作用如下:
      1. 向一个未打开的端口发送连接请求
      2. 应用程序主动终止一个连接
      3. 应用程序还没有接收缓存中的数据,连接被提前关闭
      4. TWA(TIME-WAIT Assassination)
      5. 半开连接的情况下发送数据。参考 此处
    • SYN(Synchronize) :该标志仅在三次握手建立TCP连接时有效。它提示TCP连接的服务端检查序列编号.
    • FIN(Finish) :带有该标志置位的数据包用来结束一个TCP会话,但对应端口仍处于开放状态 ,准备接收后续数据。
  • 选项(Option) :长度不定,但长度必须以是32bits的整数倍。常见的选项包括 MSS、SACK、Timestamp 等。可用于填充

    可选字段的格式

    选项含义

    常用选项为:

    • 最大报文传输段(Maximum Segment Size — MSS )MSS只出现在前两次握手中

      MSS 是传输层 TCP 协议范畴内的概念,顾名思义,其标识TCP能够承载的最大的 应用数据 长度,因此,MSS = MTU - 20 字节TCP报头 - 20字节IP报头,那么 在以太网环境下,MSS值一般就是1500-20-20=1460字节

    • 窗口扩大选项(window scaling – WSOPT )该选项只出现在前两次握手中 ,因此当TCP连接建立起来后,window scale就固定了。

      window size 占 16 位,最大 64 kb,在网络情况很好的状态下,这么小的窗口无法满足较高的网络性能,所以需要用 WSOPT 选项扩大窗口。该选项格式如下:

       //         +---------+---------+---------+
       //         | Kind=3  |Length=3 |shift.cnt|
       //         +---------+---------+---------+
      

      当使用 WSOPT 选项的时候,接收窗口的实际大小则为 Window Size << shift.cnt,其中 shift.cnt 按照协议最大只能为14 ,当接收端接收到的 shift.cnt 大于 14 的时候,则按照 14 来处理 Window Size 。WSOPT 选项最大可将原有的 16 位 Window Size 扩展到近 30 位大小(大约1GB),可以有效提升TCP允许使用的接收缓存。

    • 选择确认选项(Selective Acknowledgements —SACK ) :用于重传和拥塞控制,笔者其他文章会详述。

    • 时间戳选项(timestamps ) :用于 测量往返时延 (RTTM,利于掌握网络拥塞信息),防止序列号回绕 (PAWS)(参见:序列号回绕

    • NOP选项部分的每种选项长度必须是4字节的倍数,不足时用NOP补充 。注意,是用来填充选项之间的空隙。

    • EOL :用来填充整个选项部分的末尾。

      举例:假如 Header Length 指定的 TCP 头长为 40 bytes,其中第 29-38 bytes 为 TSOPT 选项,则可以在第 39 byte 处添加一个 EOL 选项指示选项列表结束,可以看到 EOL 并没有位于 TCP 头的结束位置的第 40 byte。对于最后一个 byte RFC793 协议规定需要以 0 来填充。这个EOL后面填充的 0 已经不属于 TCP 选项的一部分了。然而,linux 本身发送 TCP 数据包的时候并不会添加 EOL 选项,而是通过添加一个或者多个 NOP 选项来实现整个 TCP 头长的四字节对齐。

    • FOC :用于 TFO 的 Cookie 选项,参见此处

文章参考:

TCP协议01 ,姜知笔记 ,TCP那些事 , TCP 8 , 《计算机网络自顶向下》

文章作者: 极简
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 后端技术分享
网络理论
喜欢就支持一下吧