5.9 TCP报文段的首部格式
# 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整除,则需要使用填充字段来确保首部能被四整除。
本节课的内容小结如下