5-9 TCP 报文段的首部格式
# 590.5-9 TCP报文段的首部格式
本节课我们介绍 TCP 报文段的首部格式。
在之前的课程中我们曾介绍过,为了实现可靠传输,TCP 采用了面向字节流的方式,如图所示 TCP 将应用进程交付下来的应用报文看作是字节流,存入 TCP 发送缓存中,但 TCP 在发送数据时是否发送缓存,取出一部分或全部字节,并给其添加一个首部使之成为 TCP 报文段后进行发送。
一个 TCP 报文段,有首部和数据载荷两部分构成。TCP 的全部功能,都体现在它首部中各字段的作用。
接下来我们就来看看 TCP 报文段的首部格式,TCP 报文段的首部格式与 IP 数据报的首部格式类似,都是由二十字节的固定首部和最大四十字节的扩展首部构成:
我们首先来看源端口和目的端口字段,源端口字段占 16 比特,用来写入源端口号,而源端口号用来标识发送该 TCP 报文段的应用进程,目的端口号字段占 16 比特,用来写入目的端口号,而目的端口号用来标识接收该 TCP 报文段的应用进程。
我们来举例说明源端口和目的端口的作用。
假设主机中的浏览器进程要访问 WEB 服务器中的 WEB 服务器进程,为了简单起见,我们仅从运输层端口号这个角度来举例说明,而不考虑其他细节。例如 ARP、域名解析,TCP 连接建立等。当在浏览器地址栏中输入了外部服务器的域名后,浏览器进程会构建一个封装有 HTTP 请求报文的 TCP 报文段,该报文段首部中的源端口字段,会填写一个短暂端口号,例如 49152 用来标识发送该报文段的浏览器进程,目的端口字段会填写熟知端口号 80,因为是用 HTTP 协议的 WEB 服务器进程,默认监听该端口,WEB 服务器收到该 TCP 报文段后,从中解封出 HTTP 请求报文,并根据 TCP 报文段首部中目的端口字段的值 80,将 HTTP 请求报文上交给 WEB 服务器进程,WEB 服务器进程根据 HTTP 请求报文的内容进行相应处理,并构建一个 HTTP 响应报文,HTTP 响应报文需要封装成 TCP 报文段进行发送。
该报文段首部中的源端口字段,会填写熟知端口号 80,用来标识发送该 TCP 报文段的 WEB 服务器进程,而目的端口字段会填写 49152,这是主机中需要接收该 TCP 报文段的浏览器进程所对应的端口号。主机收到该 TCP 报文段后,从中解封出 HTTP 响应报文,并根据 TCP 报文段首部装目的端口字段的值 49152,将 HTTP 响应报文上交给浏览器进程,浏览器进程对 HTTP 响应报文的内容进行解析并显示。
接下来我们再来看看与 TCP 实现可靠传输相关的序号字段,确认号字段以及确认标志位 ACK。序号字段占 32 比特,因此取值范围是 0~2 的 32 次-1,当序号增加到最后一个后,下一个序号就又回到 0。序号字段的值用来指出本 TCP 报文段数据载荷的第一个字节的序号。例如这是一个 TCP 报文段,它有首部、数据载荷两部分构成,数据载荷中的每个字节数据都有序号,如图所示,请注意他们是字节数据的序号而不是内容。对于本例首部中序号字段应填入的 10 进制值为 166,用来指出数据载荷的第一个字节的序号为 166。
确认号字段占 32 比特,因此取值范围是 0~2 的 32 次-1,当确认号增加到最后一个后,下一个确认号就要又回到 0。确认号字段的值用来指出希望收到对方下一个 TCP 报文段的数据载荷的第一个字节的序号,同时也是对之前收到的所有数据的确认。可以这样理解,若确认号等于 N 则表明到序号 N-1 为止的所有数据都以正确接收,希望接收序号为 N 的数据,只有当确认标志为 ACK 取值为 1 时,确认号字段才有效,取值为 0 时,确认号字段无效。TCP 规定在连接建立后,所有传送的 TCP 报文段都必须把 ACK 置 1.
我们来举例说明这三个字段的作用。TCP 客户进程发送一个 TCP 报文段,该报文段首部中序号字段的取值为 201,这表示该 TCP 报文段数据载荷的第一个字节的序号为 201,假设数据载荷的长度为 100 字节,首部中确认号字段的取值为 800,这表示 TCP 客户进程收到了 TCP 服务器进程发来的序号到 799 为止的全部数据,现在期望收到序号从 800 开始的数据,为了使确认号字段有效,首部中的确认标志位 ACK 的值必须设置为 1。
TCP 服务器进程收到该报文段后,也给 TCP 客户进程发送 TCP 报文段,该报文段首部装序号字段的取值为 800,这表示该 TCP 报文段数据载荷的第一个字节的序号为 800,这正好与 TCP 客户进程的确认相匹配,假设数据载荷的长度为 200 字节,首部中确认号字段的取值为 301,这表示 TCP 服务器进程收到了 TCP 客户进程发来的序号到 300 为止的全部数据,现在期望收到序号从 301 开始的数据,为了使确认号字段有效,首部中的确认标志为 ACK 的值必须设置唯一。
我们再来看数据偏移字段,该字段占 4 比特,并以四字节为单位,用来指出 TCP 报文段的数据载荷部分的起始处,距离 TCP 报文段的起始处有多远,该字段实际上指出了 TCP 报文段的首部长度,首部固定长度为 20 字节,因此数据偏移字段的最小值为二进制的 0101,加上最大扩展首部 40 字节,首部最大长度为 60 字节,因此数据偏移字段的最大值为二进制的 11111。我们来举例说明,假设这个 TCP 报文段首部中的数据偏移字段的取值为二进制的 0101,那么首部长度就为 20 字节,因为二进制的 0101 的 10 进制值是 5,而该字段以四字节为单位,因此 5×4 字节=20 字节。假设这个 TC 报文段首部中的数据偏移字段的取值为二进制的 1111,那么首部长度就为 60 字节,因为二进制 1111 的 10 进制值为 15,而该字段以四字节为单位,因此 15×4 字节等于 60 字节。
TCP 报文段首部中的保留字段占 6 比特,保留为今后使用,目前应至为 0。
我们再来看看窗口字段,该字段占 16 比特,以字节为单位,该字段指出的是发送本报文段的一方的接收窗口,窗口值作为接收方让发送方设置其发送窗口的依据,这是以接收方的接收能力来控制发送方的发送能力,也就是所谓的流量控制,需要注意的是发送窗口的大小还取决于拥塞窗口的大小,也就是应该从接收窗口和拥塞窗口中取小者。
TCP 报文段首部中的校验核字段占 16 比特,用来检查整个 TCP 报文段在传输过程中是否出现了误码,与 UDP 类似。在计算校验和时要在 TCP 报文段的前面加上 12 字节的尾首部,具体的校验算法就不再赘述了,因为它仅仅是一种检测算法,与 TCP 的其他重要功能相比,检错算法并不是重点。
接下来我们来看同步标志位 SYN 该标志位在 TCP 连接建立时用来同步序号,如图所示,这是我们之前课程中曾介绍过的,TCP 通过三报文握手建立连接的过程,TCP 客户进程发送的 TCP 连接请求报文段,首部中的同步标志位 SYN 被置 1,表明这是一个 TCP 连接请求报文段,TCP 服务器进程发送的 TCP 连接请求确认报文段,首部中的同步标志位 SYN 被置 1,确认为 ACK 也被置 1,表明这是一个 TCP 连接请求确认报文段。
再来看看终止标志位 FIN,该标志位用来释放 TCP 连接,如图所示,这是我们之前课程中曾介绍过的,TCP 通过四报文挥手释放连接的过程,不管是 TCP 客户进程还是 TCP 服务器进程,他们所发送的 TCP 连接释放报文段,首部中的终止标志位 FIN 都被置 1,表明这是 TCP 连接释放报文段,
首部中的复位标志位 RST 用来复位 TCP 连接,当 RST 等于 1 时表明 TCP 连接出现了异常,必须释放连接,然后再重新建立连接,RST 置 1 还可以用来拒绝一个非法的报文段,或拒绝打开一个 TCP 连接。
首部中的推送标志位 PSH 用来实现推送操作。当接收方的 TCP 收到该标志位为 1 的报文段,会尽快上交应用进程,而不必等到接收缓存都填满后再向上交付。首部中的紧急标志位 URG 和紧急指针字段用来实现紧急操作,紧急标志为 URG 取之为 1 时,紧急指针字段有效,取值为 0 时,紧急指针字段无效,紧急指针字段占 16 比特,以字节为单位,用来指明紧急数据的长度。当发送方有紧急数据时,可将紧急数据插队的发送缓存的最前面,并立刻封装到一个 TCP 报文段中进行发送。紧急指针会指出本报文段数据载荷部分包含了多长的紧急数据,紧急数据之后是普通数据,接收方收到紧急标志为 1 的报文段,会按照紧急指针字段的值,从报文端数据载荷部分取出紧急数据,并直接上交应用进程,而不必在接收缓存中排队。
TCP 报文段首部除了 24 节的固定部分,还有最大 40 节的选项部分,增加选项可以增加 TCP 的功能。目前有以下选项,
最大报文段长度选项 MSS,它用来指出 TCP 报文段数据载荷部分的最大长度;
窗口扩大选项,用来扩大窗口,提高吞吐率。
时间戳选项有以下两个功能,一个是用来计算往返时间,另一个是用来处理序号超范围的情况,要称为防止序号绕回 PAWS,选择确认选项,用来实现选择确认功能。
由于选项的长度可变,因此还需要使用填充字段来确保报文段首部能被四整除。这是因为数据偏移字段,也就是首部长度字段是以四字节为单位的,如果选项的长度加上 20 字节固定首部的长度不能被 4 整除,则需要使用填充字段来确保首部能被四整除。
本节课的内容小结如下: