12.3 TCP头部和封装

​ 下图显示了TCP在IP数据报中的封装:
TCP头部格式和封装_c
​ TCP头部紧跟着IP头部或者IPv6扩展头部,经常是20字节(默认不带选项字段)。带选项字段的话,TCP头部最长可达60字节。常见的选项字段包括最大段大小时间戳窗口缩放选择性ACK等。

​ TCP的头部要比UDP等协议的复杂的多,因为保持连接的每一段都需要支持最新的状态信息。TCP头部格式如下图所示:
TCP头部格式和封装_c_02

TCP头部的标准长度为20字节,除非出现选项字段。头部长度字段以4字节为单位给出头部大小(最小值为5)。带阴影的字段(确认号(Acknowledagment Number)、窗口大小(Window Size)以及ECE位和ACK位)用于与该报文段的发送方关联的反方向上的数据流。

字段 长度 含义
源端口 16比特 源端口,标识哪个应用程序发送
目的端口 16比特 目的端口,标识哪个应用程序接收
序列号 32比特 序号字段。TCP链接中传输的数据流中每个字节都编上一个序号。序号字段的值指的是本报文段所发送的数据的第一个字节的序号。
确认号 32比特 确认号,是期望收到对方的下一个报文段的数据的第1个字节的序号,即上次已成功接收到的数据字节序号加1。只有ACK标识为1,此字段有效。
首部长度 4比特 首部长度指出TCP报文段的数据起始处距离TCP报文段的起始处有多远,以32比特(4字节)为计算单位。最多有60字节的首部,若无选项字段,正常为20字节。
保留位 4比特 必须填0
CWR 1比特 拥塞窗口减(发送方降低它的发送速率)
ECE 1比特 ECN回显(发送方收到一个更早的拥塞通告)
URG 1比特 紧急指针有效标识。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据)。很少被使用
ACK 1比特 确认序号有效标识。只有当ACK=1时确认号字段才有效。当ACK=0时,确认号无效。
PSH 1比特 标识接收方应该尽快将这个报文段交给应用层。接收到PSH = 1的TCP报文段,应尽快的交付接收应用进程,而不再等待整个缓存都填满了后再向上交付。
RST 1比特 重建连接标识。当RST=1时,表明TCP连接中出现严重错误(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立连接。
SYN 1比特 同步序号标识,用来发起一个连接。SYN=1表示这是一个连接请求或连接接受请求。
FIN 1比特 发端完成发送任务标识。用来释放一个连接。FIN=1表明此报文段的发送端的数据已经发送完毕,并要求释放连接。
窗口大小 16比特 窗口:TCP的流量控制,窗口起始于确认序号字段指明的值,这个值是接收端正期望接收的字节数。窗口最大为65535字节。
校验和 16比特 校验字段,包括TCP首部和TCP数据,是一个强制性的字段,一定是由发端计算和存储,并由收端进行验证。在计算检验和时,要在TCP报文段的前面加上12字节的伪首部
紧急指针 16比特 紧急指针,只有当URG标志置1时紧急指针才有效。TCP的紧急方式是发送端向另一端发送紧急数据的一种方式。紧急指针指出在本报文段中紧急数据共有多少个字节(紧急数据放在本报文段数据的最前面)。
选项 选项字段。TCP协议最初只规定了一种选项,即最长报文段长度(数据字段加上TCP首部),又称为MSS。MSS告诉对方TCP“我的缓存所能接收的报文段的数据字段的最大长度是MSS个字节”。 新的RFC规定有以下几种选型:选项表结束,无操作,最大报文段长度,窗口扩大因子,时间戳。 窗口扩大因子:3字节,其中一个字节表示偏移值S。新的窗口值等于TCP首部中的窗口位数增大到(16+S),相当于把窗口值向左移动S位后获得实际的窗口大小。 时间戳:10字节,其中最主要的字段是时间戳值(4字节)和时间戳回送应答字段(4字节)。 选项确认选项:

12.3.1 端口号

​ 每一个TCP头部都包含了源端口和目的端口。这两个值与IP头部中的源和目的IP地址唯一标识一个连接(四元组)。这个特点在TCP服务器同时与多个客户端提供服务时特别重要,服务器就是根据四元组信息(或者五元组信息)来确定客户端的。

12.3.2 序列号

用于判断接收方是否重复接收到某一报文以及报文的乱序重组功能

​ 该字段标识了TCP发送端到TCP接收端的数据流中的一个字节,该字节代表着包含该序列号报文段的数据中的第一个字节。如果我们考虑在两个应用程序之间的一个方向上流动数据流,TCP给每一个字节赋予一个序列号。这个序列号是一个32位的无符号整数,到达2^32 -1 后再循环从0开始。因为每一个没交换的字节都被编号,确认号字段(ACK位置1,确认号字段生效)包含的值是数据的接收方(即ACK的发送方)期待接收到的下一个序列号。即最后被成功接收的数据字节序号加1。这个字段之后再ACK位被启动的情况才有效。

  • 当建立一个连接时,从客户端发送至服务器的第一个报文段中的SYN位字段被启用。这样的报文段简称为SYN;并且序列号字段包含了在这个方向上要是用的第一个序列号后续的序列号和返回的ACK都在这个方向上

    • 注意:这个初始的序列号不是0或1,而是随机生成的一个数值,成为初始序列号(Inital Sequence Number, 简称ISN), ISN不是0/1,是为了提高安全性,防止被黑客攻击利用。

    • 客户端发送的第一个报文时,第一个字节的序列号为ISN+1, 这意味着SYN报文消耗一个序列号,而消耗一个序列号意味着可以使用重传机制进行可靠传输。因此SYN、以及FIN报文是可以可靠传输的,而ACK报文不消耗序列号,因此无法保证ACK报文的可靠传输

  • TCP可以被描述为“一种带积累正向确认的滑动窗口协议”。ACK确认号字段被用于构建知名在接收方已经顺序收到的最大字节(确认号 -1 = 成功接收的字节)。然而现代的TCP有一个选择确认(Selective Acknowledgment, SACK)选项,可以允许接收方告诉发送方它正确的接收到的次序杂乱的数据。 当它与一个具有选择重发(selective repeat)能力的TCP进行通信时,可以显著的提高通讯效率。

12.3.3 头部长度

​ 头部长度用来指出TCP头部的长度,以32比特为单位,由于存在选项字段,因此它是必须的。它的长度为4比特,因此TCP头部的长度限定为20~60字节(15*4=60),如果不带选项字段,即标准头部长度为20字节。

12.3.4 相关控制位

​ 当前,为TCP头部定义了8位的字段,尽管有些老的实现只能理解最后的6位。

  • CWR : 拥塞窗口减(发送方减低它的发送速率)
  • ECE : ECN回显(发送方接收到了一个更早的拥塞通告)
  • URG : 紧急(紧急指针字段有效,很少被用到)
  • ACK : 确认 (确认号字段有效,连接建立后一般都处于启用状态)
  • PSH : 推送 (接收方应尽快给应用程序发送这个数据,目前没有可靠地实现或者用到)
  • RST : 重置连接 (当前连接关闭,重新建立新的连接)
  • SYN : 用于初始化一个连接的同步序列号
  • FIN : 该报文的发送方已经没有数据要发送,请求对方关闭当前连接。

12.3.5 窗口大小

​ TCP的流量控制是通过通告窗口大小来控制实现的。这个窗口大小是指字节数,从确认号指定的,也就是从接收方想要接收的那个数据开始计算的。它是一个16比特的字段,因此限定了TCP的窗口大小最大为65535字节,从而限制了TCP的吞吐量性能。这个值可以通过窗口缩放手段进行修改。

12.3.6 校验和

​ TCP的校验和字段覆盖了TCP头部和TCP数据,还包括一个伪头部。这个字段是强制性的,必须由发送方计算和保存、接收方进行验证。它与计算UDP的校验和方式相同。

12.3.7 选项字段

选项字段最最重要的就是MSS字段(又称为最大段大小)。连接的每一个端点一般都在它的第一个SYN报文上指定MSS的值,用来标明自己希望接收的最大段的消息。