计算机网络学习笔记:第三章

计算机网络学习笔记:第三章

学习书籍:《计算机网络:自顶向下方法》 第三章:运输层

其他章节请参阅:
《计算机网络:自顶向下方法》 第一章:计算机网络和因特网
《计算机网络:自顶向下方法》 第二章:应用层
《计算机网络:自顶向下方法》 第三章:运输层
《计算机网络:自顶向下方法》 第四章:网络层:数据平面



前言

运输层位于应用层和网络层之间,是分层的网络体系的重要部分;该层为运行在不同主机上的应用进程提供直接的通信服务起着至关重要的作用。在这里我们将讨论两个大的问题:将网络层在不同端系统之间的通信服务扩充到运行在两个端系统上不同的应用层进程之间的通信服务(如何实现进城之间通信的可靠传输)和控制传输层实体的传输速度以避免网络拥塞或者从网络拥塞中恢复过来,这里需要考虑的有拥塞的后果和原因以及常见的拥塞控制手段;特别的,我们将了解TCP协议中的拥塞控制

3.1、概述和运输层服务

传输层协议为运行在不同端系统上的应用进程之间提供逻辑通信功能;应用层进程使用传输层提供的逻辑通信功能而无需考虑实现通信的物理基础设施的细节

传输层协议是在端系统中实现的而不是在路由器中实现的。传输层接收来自应用层的报文并通过添加传输层首部以生成传输层报文段。在生成过程中可能会对来自应用层的报文加以分割;然后在发送端系统中,运输层会将这些报文段交给网络层;网络层将其封装成网络层分组,也被称为数据报,然后向目的地发送。路由器不会检查封装在数据报中的传输层报文段的字段;在接收端,网络层从数据报中抽取传输层报文段,并将其交给运输层,运输层接收到报文段后,使该报文段中的数据被接收应用进程所使用。

网络应用可以使用多种传输层协议,因特网有两种传输层协议,即TCP和UDP,不同的传输层协议提供不同的运输层服务;

3.1.1 运输层和网络层的关系

在协议栈中,运输层刚好位于网络层之上;网络层提供主机之间的逻辑通信而传输层为运行在不同主机上的应用进程提供逻辑通信;运输层协议只工作在端系统中。在端系统中,传输层协议将来自应用进程的报文移动到网络边缘即网络层,反过来也从网络层接收这些报文段;传输层对报文段如何在网络核心传输并不做干涉;事实上中间路由器既不处理也不识别传输层加载应用层报文上的任何信息

运输层协议能提供的服务常常受制于底层网络层协议的服务类型,如果网络层协议无法为主机之间的通信提供时延带宽保证的话,运输层协议也就无法为进程之间发送的应用程序报文提供时延或者带宽保证;

然而即使底层网络协议不能在网络层提供响应的服务,运输层协议也能提供某些服务。例如,即使底层网络协议是不可靠的,运输协议也能为应用程序提供可可靠的数据传输服务(即使底层网络协议不可靠,使分组丢失和篡改,运输协议也能为应用程序提供可靠的的数据传输服务)。

3.1.2 因特网运输层概述

因特网为应用层提供了截然不同的两种传输层协议:UDP(用户数据报协议)它提供一种不可靠无连接的服务;另一种是TCP,它提供可靠的面向连接的服务;运输层分组也被称为报文段

简单了解一下因特网的网络层,网络层协议有一个名字即IP,即网际协议。IP为主机间提供逻辑通信,IP的服务模型为尽力而为交付服务(best-effort delivery service)这意味着IP尽最大的努力在主机间交付报文段,但是不做任何保证。它不保证报文段的交付不保证报文段按序交付不保证报文段中数据的完整性;即IP提供一种不可靠的服务;每台主机都需要有一个网络层地址,即IP地址。

UDP和TCP最基本的责任就是将IP提供的主机间交付服务扩展到不同端系统上两个进程之间的服务,这也被称为传输层的多路分解多路复用;UDP和TCP通过在传输层首部添加差错检查字段来提供完整性检查进程到进程之间的数据交付差错检查是最低限度的两种传输层服务,也是UDP可以提供的仅有的两种服务。UDP和IP一样,也是不可靠服务;

TCP提供额外的服务,首先它是一种可靠数据服务,这意味着TCP协议保证数据的按序、完整地从发送端应用进程发送到接收端应用进程;TCP通过流量控制、序号、确认和定时器,将IP的不可靠数据传输转换为可靠数据传输;其次,TCP提供拥塞控制,拥塞控制与其说是一种提供给应用程序的服务,不如说是一种提供给整个网络的服务,因为整个网络都将因为拥塞控制而受益;不太严格地说,拥塞控制力求为每一个经过一条拥塞网络的连接提供平等的共享网络链路带宽,从而避免一条TCP连接用过多的流量来淹没通信主机之间的链路和设备;TCP的拥塞控制是通过调节发送进网络的的流量速率来做得到;UDP不提供拥塞控制,使用UDP传输的应用程序可以根据需要以任意的速率发送数据。

3.2、多路复用与多路分解

前文提到,传输层将网络层提供的面向主机的逻辑通信扩充为面向不同应用进程的逻辑通信,并且这一过程称为多路复用和多路分解;多路复用和多路分解是每个计算机网络都需要的;

在目的主机,运输层从紧邻其下的网络层接收报文段;运输层负责将这些报文段中的数据交付给在主机上运行的应用程序进程; 2.7节提到,一个进程有一个或者多个套接字,相当于从网络向进程传递数据和从进程向网络传递数据的门户;传输层和应用程序进程之间通过套接字关联,接收主机的运输层实际上并没有直接将数据交付给进程,而是将将数据交付给中间的一个套接字;在任一时刻,接收主机上可能不止一个套接字每个套接字都有唯一标识符

传输层从同一台主机上的不同Socket接收数据的过程称为多路复用传输层向同一台主机上的不同Socket传输数据的过程称为多路分解;为了实现多路复用和多路分解,我们需要标志套接字,并将相关信息添加到报文段中。

传输层多路复用要求:1)套接字有唯一标识符;2)每个报文段都有源端口号字段和目的端口号字段来指示该报文段所要交付到的套接字;
端口号大小在0-65535之间,其中0-1023属于周知端口号,它们为特定的Socket而拥有。
运输层如何实现分解服务:主机上每个套接字能分配一个端口号;报文达到主机时,运输层检查报文段的目的端口号,并将其定向到相应套接字,然后报文段中数据通过套接字进入其所连接的进程;UDP大致是这样做的,TCP更复杂;

无连接的多路复用与多路分解

需要注意的是,在创建Socket的时候,是由传输层为之分配端口号;一个UDP套接字是由一个目的IP地址目的端口号(即二元组)来标志的;如果两个UDP报文段有不同的源IP地址或者源端口号,但是有相同的目的IP和目的端口号的话,它们将通过同一个Socket到达同一个应用程序;

源端口号的用途:例如A到B的报文段中,源端口号作为“返回地址”的一部分,即当B要回发一个报文段给A,B到A的报文段中的目的端口号便从A到B的报文段中的源端口号取值(完整返回地址还包括A的IP地址);

面向连接的多路复用和多路分解

TCP协议中的Socket是通过一个四元组来标记的:(源IP地址,源端口号,目的IP地址,目的端口号);两个具有不同源IP地址或者源端口号,但有相同的目的IP地址和目的端口号的TCP报文段将通过两个不同的Socket进入同一应用进程;这也表示,一个应用进程可以关联多个Socket,而一个Socket将只关联一个应用进程;常常,这样的对应关系是通过线程来实现的:一个进程有多个线程,而每个线程关联了一个Socket;这样做可以提高服务器性能;

实际上,传输层就是根据这些信息来实现多路分解的;而这些信息是在多路复用的时候被放置在报文段中的;

3.3、无连接运输:UDP

如果设计一个不提供不必要服务的传输层协议会是什么样的呢?传输层协议必须提供的功能有差错检查和进程到进程的数据交付,事实上,UDP的确做到了这些,并且只做了这些。它几乎没有对IP增强别的东西;因为在发送报文段之前,发送方和接收方的传输层实体之间没有握手,所以UDP也被称为无连接的;

DNS是一个使用UDP的应用层协议例子;UDP在接收到来自Socket的数据时,UDP为该报文添加首部字段(源和目的端口号,以及其他两个小字段),然后将报文段交给网络层,网络层通过IP协议尽力地将该报文段交付,至于结果,尽力就好;当DNS客户端等待不到对该查询的响应时(有可能网络层将其丢失了)则会向其他Name Server发送查询请求,要么就通知应用程序,做不到;

既然TCP提供了可靠数据传输,并且提供了拥塞控制,为什么人们还需UDP呢?事实上,有些应用很适合UDP,UDP有以下好处

  1. 关于何时、发送什么数据的应用层控制更为精细:这是因为一旦应用程序将数据交给UDP,UDP就会打包将其发送给网络层,不会受到传输层的调节,这在一些实时应用中比较实用;当然,应用程序还可以通过UDP+自主开发一些功能的模式来扩展UDP。
  2. 无需建立连接:所以就不会引入额外的时延,这也可能是DNS使用UDP而不是TCP的主要原因;HTTP使用TCP的主要原因是对TCP的可靠性的依赖超过对速度的要求;
  3. 无需维护连接状态:TCP为了实现可靠数据传输和拥塞控制需要在端系统中维护一些参数,这些参数包括:接收和发送的缓存、拥塞控制参数、确认号和序号;这些参数信息都是必须的;而UDP因为不建立连接,所以自然也就不需要维护这些状态,这就减少了时空开销;
  4. 分组首部更小:TCP有20字节的首部开销,而UDP只有8字节;

通常使用TCP作为其传输层协议的应用程序:电子邮件、远程终端访问、Web、文件传输;
通常使用UDP作为其传输层协议的应用程序:远程文件服务器、网络管理(因为这里应用即便在网络处于拥塞的情况下仍要工作,所以UDP更为合适)、路由选择协议和名称转换(DNS);
这些应用两个都有使用:流式多媒体、因特网电话等多媒体应用;这些应用对实时性的要求较高同时对可靠性的要求又不是很高,所以既可以使用UDP也可以使用TCP协议。

不过在UDP之上运行多媒体应用是有争议的,因为UDP没有拥塞控制协议,所以其对网络有很大的威胁性:大量的UDP流量将使网络过度拥塞而造成TCP连接几乎无法传输数据,并且因为网络拥塞,所以应用又有着较高的丢包率,而因为丢包率UDP很有可能继续发送数据,由此使得网络效率低下。也有研究人员提出一些新的机制,使得所有数据源,包括UDP源执行自适应的拥塞控制来解决这一问题;

需要注意的是,使用UDP仍然可以实现可靠数据传输,只不过这一部分功能需要在应用程序中自主开发;将可靠性直接构建于应用程序中,将使其既可以可靠地传输数据又可以避免受制于TCP的拥塞控制(传输速率的控制)

3.3.1 UDP 报文段格式

在这里插入图片描述

UDP首部只有4个字段每个字段占用两个字节,分别是:源端口号、目的端口号、长度和校验和
其中,长度表示包含首部在内的UDP报文段长度,以字节为单位;
校验和字段用来计算报文段在传输的过程中是否出现了差错;一种常见的校验和的计算方法是:发送方将前三个字段做按位加运算,然后将其取反作为校验和;然后接收方对所有四个字段(每个字段16位)进行求和,如果没有出现差错,则最后的结果全是1,否则就表明出现了错误;出现错误的原因可能有:传输链路上数据受到干扰或者数据存储在中间路由器的时候出现了错误;

UDP作为传输层协议,提供的差错检测功能很有可能和底层协议提供的相似功能产生冗余;但是,这是必须的,因为由于不能保证源和目的地之间所有链路都提供差错检测功能,即便数据在链路上正确传输,也无法保证其在中间路由器的内存中不发生错误;所以要实现端到端的差错检测,就必须在传输层协议中实现该功能
这一原则在系统设计中被称为端到端原则:“因为某一功能必须在端到端实现,与在较高层次提供这些功能的代价相比,在较低层次上设置的功能可能是冗余的,或者根本是没有用的;

IP作为网络层协议,可以运行在任何第二层协议上,所以运输层提供差错检测也是必须的;UDP可以检测差错,但是无法恢复差错,能做的除了将其丢弃外,便是将其交给应用程序然后给出警告;

3.4、 可靠数据传输原理

在这里插入图片描述

可靠数据传输的问题,不仅在传输层需要考虑,在链路层以及应用层都需要考虑这个问题,所以了解一些其基本原理是必要的;
如图所示,可靠数据传输为上层实体提供的服务抽象是:数据可以通过一套可靠的信道进行传输,借助于可靠信道,传输数据就不会受到损坏或者丢失;并且所有数据都可以按照其发送顺序进行交付,而这正是TCP向调用它的应用所提供的服务模型;

实现这种抽象服务是可靠数据传输协议的责任,但是因为可靠数据传输的底层协议可能是不可靠的,所以这项任务有一点困难;例如,TCP就是在不可靠的(IP)端到端网络层之上实现的可靠数据传输协议;

单方向的可靠数据传输流程大概是这样的:可靠数据传输->不可靠数据传输->不可靠的传输信道->可靠数据接收->上传Data;

3.4.1 构造可靠数据传输协议

一个可靠数据传输协议,将要面对以下问题:分组丢失分组损坏到达分组乱序到达

总结可靠传输需要的技术:检验和、序号、定时器、肯定和否定确认分组。

  1. 经完全可靠信道的可靠数据传输:rdt 1.0
    在这里插入图片描述

首先考虑最简单情况,底层通道完全可靠(所以接收端不需要提供反馈信息给发送方);上图显示rdt 1.0发送方和接收方的有限状态机(Finite-State Machine, FSM),发送方和接收方都有各自的FSM,FSM伤的箭头表示协议从1个状态变迁到另1个状态;引起变迁的事件显示在表示变迁的横线上方,事件发生时采取的动作显示在横线下方;

  1. 经具有比特差错信道的可靠数据传输:rdt 2.0
    在这里插入图片描述

假设所有发送的分组都可以按其发送顺序被接收。基于重传机制的可靠数据传输协议称为自动重传请求(ARQ)协议,增加了肯定确认(ACK)和否定确认(NCK);

ARQ协议中还需要另外三种协议功能来处理存在比特差错的情况:差错检测,使接收方检测到何时出现比特差错;接收方反馈重传

rdt2.0的发送端每发送一个分组需要等待接收端的确认信号,这种协议被称为停等协议。也就是说,当发送方处于等待ACK或者NA卡状态时,它不能从上层获得更多数据;

  1. rdt 2.1

rdt 2.0 中有一个致命的缺陷,就是没有考虑到 ACK 和 NAK 分组受损的可能性。

考虑ACK和NAK受损的两个可能性:

  1. 增加足够的校验和比特,使得发送方不仅可以检测差错,还可以恢复差错。对于产生差错但不丢失分组的信道,可直接解决问题;
  2. 当接受到模糊不清的ACK和NAK分组时,只需要重传当前数据分组,但这引入了冗余分组冗余分组的根本困难在于接收方不知道它上次所发送的ACK和NAK是否被发送方正确接收到。因此它无法事先知道接收到的分组是新的还是一次重传。

解决这个新问题的一个简单的方法就是在数据分组中添加一个字段,让发送方对其数据分组编号,即将发送数据分组的序号放在该字段。于是,接收方只需要检查序号即可确定收到的分组是否一次重传。对于停等协议这种简单的情况,1 比特的序号就足够了,因为它可以让接收方知道发送方是否正在重传前一个发送分组或是一个新分组;

rdt2.1的发送方和接收方FSM状态书都是rdt2.0的两倍,协议此时必须反应目前正在发送的分组和希望接受的分组序号是0还是1;值得注意的是,希望或期望接收0号/1号分组的状态中的动作是一样的,唯一区别是序号处理方法不同;

在这里插入图片描述
4. rdt 2.2

如果不发送NAK,而是对上次正确接收的分组发送一个ACK,我们也能实现同样的效果。发送方接收到对一个分组的两个ACK(冗余ACK)后,就知道接收方没有正确接收到跟在确认两次的分组后面的分组。

rdt 2.2 是在有比特差错信道上实现的一个无NAK的可靠数据传输协议。rdt 2.1和rdt 2.2的区别在于,接收方此时必须包括由一个ACK报文所确认的分组序号

在这里插入图片描述

  1. 经具有比特差错的丢包信道的可靠数据传输:rdt3.0
    在这里插入图片描述

在 rdt 3.0 中,让发送方负责检测和恢复丢包工作。不管是发送的分组丢失,还是接收方返回的确认分组丢失,只要在经过一定的时延后,让发送方重发该分组即可。由此产生的冗余数据分组(接收端很长时间没有给确认信息,数据不一定丢失了,但发送方重传了分组)则由接收方通过序号处理。为了实现基于时间的重传机制,需要一个倒计数定时器,在一个给定的时间量过期后,中断发送方;

在这里插入图片描述

上图显示在没有丢包和延迟分组的情况下协议的运作情况,以及他是如何处理数据分组丢失的;b~d中,发送方括号部分表明定时器的设置时刻以及随和的超时;
因为分组序号在 0 和 1 之间交替,因此 rdt 3.0 有时被称为比特交替协议

归纳一下数据传输协议的要点:检验和、序号、定时器、肯定和否定确认分组;

3.4.2 流水线可靠数据传输协议

rdt 3.0 是一个功能正确的协议,但是由于它是一个停等协议,大部分的时间都浪费在等待确认上面,所以性能不好。
解决这种特殊性能问题的一个简单的方法是:不使用停等方式运行,允许发送方发送多个分组而无需等待确认。这种技术被称为流水线

要使用流水线技术,则须:

  1. 增加序号范围。因为要传送多个分组(不算重传的),而每个传输中的分组必须有一个单独的序号。
  2. 协议的发送方和接收方两端必须能缓存多个分组。发送方至少得能缓存那些已发送但未确认的分组,而接收方或许也需要缓存那些已经正确接收的分组。
  3. 所需序号的范围和对缓冲的要求取决于数据传输协议如何处理丢失、损坏及延时过大的分组

流水线的差错恢复有两种基本方法:

  1. 回退 N 步
  2. 选择重传

3.4.3 回退N步

在这里插入图片描述

在回退N步中,发送方维护一个N(窗口大小)和一个base(发送方期待收到的最小待确认分组序号,同样也是窗口的起点),还有一个next Sequence(表示上层需要发送分组时,可以使用的序号)变量。
这样全部序号就被划分为[0, base-1],这一部分的分组是已发送且收到接收方确认的分组,[base, next Sequence-1]这一部分的分组是已发送但是尚未收到确认的,其中base是尚未收到确认的最小序号;[next-1, base+N-1]表示当前发送方可以使用的序号,表示一种发送能力;大于或者等于base+N的序号不可使用
当发送方收到确认号为base的确认分组后就会向前移动窗口,所以回退N步也被称为滑动窗口协议

以上是发送方需要维护的数据,发送方需要响应的事件有:

  1. 上层调用:检查next Sequence是否在窗口之内,如果在,这说明发送方还有发送能力,发送之;
  2. 收到ACK:回退N步策略对序号为n的分组采取累积确认的方式,即当收到序号为n的ACK时,表明序号小于等于n的分组全部到位;发送方收到的ACK毕竟来自接收方,收到ACK的情况还得看接收方如何发送;
  3. 超时事件:如果发生超时事件,那么发送方会重发所有已发送但是未确认的分组,即分组号在[base, next sequence-1]之间的所有分组;这也是为什么叫“回退N步”,如果收到一个ACK,则定时器会重行启动;如果没有待确认的分组,定时器将被终止;

在接收方,如果到达分组的序号为n且该分组是按序到达,那么发送ACK,这就导致发送方移动窗口;如果不是按序到达,那么接收方丢弃所有失序分组;优点是:接收缓存简单,接收方不需要缓存任何失序分组;缺点是:可能会导致更多的重传;

在这里插入图片描述

3.4.4 选择重传(SR)

回退N步协议存在一个问题就是当窗口和带宽的时延都较大时,单个分组的差错可能会引起GBN重传大量的分组,然后许多本来不用重传的分组会充斥在信道中,造成资源浪费;选择重传就是让发送方仅重传那些丢失和受损的分组而避免不必要的重传;
在这里插入图片描述

SR 发送方的事件和动作:

  1. 从上层接收数据: 检查下一个可用于该分组的序号,若在发送方的窗口内,则将数据打包发送。
  2. 超时: 定时器再次用来防止丢失分组,但是现在每个分组必须得有单独的定时器。
  3. 收到 ACK:倘若该分组序号在窗口内,则 SR 发送方将那个被确认的分组标记为已接收。如果该分组的序号等于send_base,则窗口基序号向前移动到具有最小序号的未确认分组处。如果窗口移动了并且该序号落在窗口内的未发送分组,则发送这些分组。

SR 接收方的事件于动作:

  1. 序号在 [rcv_base, rcv_base + N -1] 内的分组被正确接收:在此情况下,收到的分组落在接收方的窗口内,一个选择 ACK 被回送给发送方。如果该分组以前没收到过,则缓存该分组。如果该分组的序号等于接收窗口的基序号,则该分组及以前缓存的序号连续的分组交付给上层。(如下图的rcv_base=2, 该分组和3、4、5一期被交付给上层)
  2. 序号在 [rcv_base - N, rcv_base - 1] 内的分组被正确接收: 产生一个 ACK,即使该分组是接收方以前已确认过的分组。(很重要!)
  3. 其他情况:忽略该分组。

在这里插入图片描述

接收方将确认一个正确接收的分组而不管其是否按序;失序的分组被缓存,直到形成连续数据后将其提交给上层;值得注意的是,如果接收方收到了已经确认的分组,则说明确认ACK丢失,或者时延太长,接收方和发送方沟通不及时;这也表明了关于那些分组到位了,那些分组还没到位,接收方和发送方有着不一样的视图。

另外还需要注意的是,序号的重用问题,如果在分组中序号字段的位数为k,那么最大的序号为2^k-1,所以有可能不同分组同时占用一个序号,为了避免这种情况,需要做的是控制分组的生命周期。窗口长度必须小于或等于序号空间大小的一半

可靠数据传输机制和用途总结:
在这里插入图片描述

3.5、面向连接的运输:TCP

TCP依赖前文中的一些原理:差错检验、重传、累积确认、定时器和用于序号和确认号的首部字段;

3.5.1 TCP连接

TCP协议之所以被称为是面向连接的协议,是因为在一个应用进程可以向另一个应用进程发送数据前,这两个进程将首先“握手”,即它们必须交换一些预报文段,已建立对关于数据传输的参数的共识;作为TCP连接建立的一部分,通信双方都将初始化与TCP连接的许多相关变量;

TCP的连接,并不是一条像电路交换网络里面端到端的TDM、FDM电路,也不是一条虚电路;其连接状态被端系统所维护而中间路由器完全忽略了该协议,中间路由器看到的只是数据,也就是说,TCP只运行在端系统之上;所以,TCP连接更像一种状态,而不是物理的、实际的连接;
TCP提供全双工服务,并且是点对点的,数据从A到B的同时,也能从B到A;TCP协议无法提供“多播”服务,一条TCP连接只关联一个发送方和接收方(当然,发送方也是接收方);

TCP建立的过程,一共发生了“三次握手”:通信的发起方首先发送一个特殊的TCP报文段给接收方,这是第一次握手;接收方收到该报文段后,对该报文段进行响应,此为第二次握手;发送方接收到响应报文段后,发送第三个报文段,其中包含了有效负载,此为第三次握手
注意⚠️:前两次报文段不承载“有效负载”,第三次握手,报文段才可以装载“有效负载”;

当TCP连接建立后,两个应用进程就可以发送数据了。应用程序将要发送的数据通过Socket传递给TCP,TCP将数据引导到该连接的发送缓存,发送缓存大小是在三次握手的过程中确定的;
之后TCP将时不时从该缓存中拿出数据进行发送,一个有趣的事情是,TCP规范中没有规定TCP应该在何时发送缓存里的数据,描述为“TCP应该在它方便的时候以报文段的形式发送数据”;
TCP每次可以从缓存中发送的最大数据长度称为MSS(Maximum Segment Size)。一般来说,MSS+TCP/IP首部的长度要小于等于链路的MTU(即链路层最大帧长度, Maximum Transport Unit)而以太网和PPP的MTU都等于1500字节,TCP/IP的首部通常为40字节,所以MSS一般来说为1460字节。
注意:MSS指的是报文段中应用层数据最大长度,而不是包括TCP首部的报文段长度。

TCP为每块客户数据加上TCP首部后就形成了多个TCP报文段;这些TCP报文段被交给网络层,然后被发送到网络中;当TCP报文段到达接收端时,便进入了接收端的缓存,等待被应用程序读取。

由上可知,TCP连接的组成包括:两台主机上的缓存、变量和与进程连接的套接字;两台主机之间的网络元素(路由器、交换机与中继器)则没有为连接分配任何缓存与变量;

3.5.2 TCP报文段结构

TCP报文段结构,从整体上来说由首部+数据字段组成;其中数据字段来自应用层,其长度不能大于MSS;首部的常规长度为20字节,但是值得注意的是,TCP首部是可变长的;TCP首部是以32比特为单位组织的,其结构组成如下图:
在这里插入图片描述

源端口号和目的端口号:这两个数据用于TCP的多路复用和多路分解;分别为16位;
32比特的序号字段:该数据被用于实现可靠数据传输之按序到达,在一个TCP连接中,算是一个报文段的id,同时该id还指示了其所承载的数据的位置信息;
16比特的接收窗口字段:用于流量控制,用于指示接收方愿意接受的字节数量;
4比特的首部长度字段:TCP的首部是可变长的,所以该字段表示报文段的首部长度,也揭示了应用数据的开始位置;该字段以32比特为单位,占4比特;
可选与变长的选项字段:该字段用于在发送方和接收方之间协商最大报文段长度(MSS)的大小;在高速网络环境下,也可用于调节窗口大小;
6比特的标记字段ACK比特表示确认号字段的里的值是否有效,如果ACK被置位,那么该报文段就对确认号所指示的报文段进行了确认;RST、SYN和FIN位用于TCP的连接和拆除;PSH被置位时,指示接收方应该立即将数据交给上层;URG被置位时表示报文段里存在着发送端的上层实体置为紧急的数据;紧急数据的最后一个字节由16位紧急数据指针字段指出。当紧急数据存在并且给出了指向紧急数据尾指针时,TCP必须通知接收端的上层实体;
_____然而,实际上,PSH、URG和紧急数据指针在实践中并没有被使用;

序号和确认号

TCP报文段中两个重要的字段是确认号和序号;这两个字段是TCP实现可靠数据传输的重要部分;TCP将数据看作是一个无结构、有序的字节流;值得注意的是,TCP的序号是基于传输的字节流之上,而不是报文段的序列之上;也就是说,来自应用层的数据被TCP包装在多个报文段中,如果MSS为1000,则第2个报文段的序列号不是2,而是1001。
关于确认号,如果采取回退N步策略,那么TCP采用一种累计确认的方法(前面已经提到过)。一条TCP连接可以采取任意数字作为初始序号,这样可以减少将那些残存在网络中的报文段误认为是新建连接的报文段(新旧连接恰巧采用了相同端口)。因为TCP只确认该流中至第一个丢失字节为止的字节 ,所以TCP被称为提供累计确认

总体来说,一个报文段的序号就是该报文段数据字段首字节的序号确认号就是接受主机正在等待接收的数据的下一个字节序号;值得注意的是,服务端对接收端发来的报文段的确认被装载到一个从服务端发往到接收端的报文段中,这种确认被称为“捎带”;

Telnet是一种应用层协议。假设用户输入一个字符‘C’,则客户与服务器之间发送TCP报文段:1)第一个报文段由客户发给服务器,数据字段里包括‘C’的ASCII码、序号字段Seq=42、确认号字段ACK=79;2)第二个报文由服务器发给客户,发送确认号ACK=43(42++)表示服务器所收到数据提供确认,和Seq=79(TCP连接中服务器到客户数据流的起始序号,也是服务器要发送的第一个序号,也就是捎带);3)客户到服务器:ACK=80(79++)和Seq=4;

3.5.3 往返时间的估计与超时

TCP使用超时/重传机制来处理报文段的问题;虽然这在概念上很简单,但是一个问题是,如何设置超时时间
如何设置超时时间,取决于网络的状态,所以需要做的是估计网络的状态。TCP使用一种Sample RTT的方法来估计RTT。Sample RTT就是从某报文段发出到收到对该报文段的确认之间的时间量。大多数TCP的实现是在某个时刻做一个Sample RTT测试。TCP并不为已经重发的报文段做Sample RTT测试,它只为传输一次的报文段测量Sample RTT。

TCP一般来说通过Estimated RTT=(1-alpha)Estimated RTT+alpha*Sample RTT (Estimated RTT的新值由以前的Estimated RTT与Sample RTT加权算得)来计算因路由器的拥塞和端系统负载变化所导致变化的RTT。
alpha一般取1/8;因为Estimated RTT表示最近的网络状况,所以其理应得到较大的权值;这种方法也被称为指数加权移动平均

除了估计RTT外,测量RTT变化也是有价值的,DevRTT =(1-b)DevRTT+b*|Sample RTT-Estimated RTT|;其中b的推荐值为0.25;当Sample RTT变化较大的时候,DevRTT的值较大,当Sample RTT变化较小的时候,DevRTT就较小;

TCP是如何考虑超时间隔的呢?该时间因略大于测量的RTT,不能过小,否则容易引起不必要的重传;也不能过大,否则网络对于报文段丢失情况的反应就会变慢;
最后TCP采用了如下计算方式:Timeout Interval=Estimated RTT+4*Dev RTT;
当出现超时后,TimeOutInteval值将加倍。不管怎么样,一旦报文段收到并更新Estimated RTT后,TimeInteval就又用上值计算了

3.5.4 可靠数据传输

前文提到,IP协议提供的是尽力而为的服务:不保证不丢失、不保证按序到达、不保证没有损坏,TCP协议在IP协议之上,提供可靠数据传输服务,从而保证一个进程从其相关联的缓存中读取的数据和另一端进程发送的数据是一致的;
TCP使用超时重传和冗余确认技术来处理超时、丢失等情况;使用确认、序号等技术来保证按序到达;使用校验和来检验是否报文段在传输过程中是否发生了错误

1.超时时间加倍

在大多数TCP实现中,当发生超时事件时,超时时间并不是从Estimated RTT和Dev RTT推算出来而是直接将超时间隔长度设置为原来的两倍;然而,每当定时器在另两个事件(收到ACK和接收到上层应用数据)发生时,新的超时间隔将由上面提到的两个值计算出来;实际上,这是一种形式受限的拥塞控制;

2.快速重传

为了响应超时事件然后重传尚未收到确认的报文段,但是,当超时间隔过长则会显著增加端到端的延迟;一种可行的方法是对冗余ACK的的检测
在理解冗余ACK之前,需要先看一下接收方为什么会发送冗余ACK:接收方接收到某个报文段时,会检查该报文段是否是按序到达,如果不是,那么接收端会发送对已经收到的最后一个连续报文段的确认,所以如果发送方收到冗余ACK,说明有多个报文段到达了接收端,但不是接收端所期望的——这意味着,很有可能发生了丢失。所以发送方可以在定时器过时之前快速重传所丢失的报文段

在这里插入图片描述
3.是回退N步还是选择重传

因为TCP采用了累计确认的机制,正确接收但失序的报文段不会被接收方逐一确认;所以,TCP发送方只需维持已发送过但没有被确认的字节的最小序号和下一个要发送的字节的序号;有些类似GBN,但是许多TCP实现都会缓存失序的分组;发生超时事件后,GBN将重传所有待确认的分组,而不是丢失的分组;但TCP会选择重传:假设分组n<N的确认报文丢失,则TCP至多重传1个报文段n,若n+1的确认报文在n超时之前到达,甚至不会重传n;

对TCP提出的一种修改意见是所谓的选择确认——即接收方对失序到达的分组也会确认,当该机制和重传机制相结合使得TCP更像选择重传,于是TCP的差错恢复协议最好被分类为GBN和SR协议的混合体;

3.5.5 流量控制

流量控制是一个速度匹配服务:TCP连接的发送方和接收方都各自维护一个缓存,因此两者的数据交换应该在一个合理的速度范围内:不让对方发生数据溢出;TCP为它的应用程序提供了这种服务:流量控制服务
前面提到TCP发送方可能因为IP服务的拥塞而被遏制,这种被成为发送方的拥塞控制;虽然流量控制和拥塞控制所采取的动作非常相似,但是它们的目的很明显并不同。下文中假设TCP接收方丢弃失序到达的报文段;

TCP让发送方维护一个接收窗口来提供流量控制,也就是给发送方指示——该接收方还有多少可用的缓存空间;因为TCP是全双工,连接两端的发送方都维护一个接收窗口。
假设主机A通过TCP连接向主机B发送一个大文件,主机B为其分配了一个接收缓存(RcvBuffer)。主机B上应用进程不时地从该缓存读取数据,LastByteRcvd表示主机B应用进程从缓存读出的数据流的最后一个字节编号,LastByteRcvd表示接收并放入主机B接收缓存中数据流最后一个字节编号;
由于TCP不允许已分配的缓存溢出,则:LastByteRcvd-LastByteRcvd<=RcvBuffer
接收窗口用rwnd表示,则rwnd = RcvBuffer- [LastByteRcvd-LastByteRcvd]

在这里插入图片描述

rwnd是动态的,如何通过rwnd来提供流量控制服务?
主机B通过把rwnd放在发给主机A的报文段接收窗口字段,通过A该连接的缓存还有多少空间;开始主机rwnd = RcvBuffer;
主机A轮流跟着两个变量:LastByteSent和LastByteAcked,LastByteSent-LastByteAcked表示主机A发送到连接但没有被确认的数据量;主机A在其连接的生命周期需保证:LastByteSent-LastByteAcked <= rwnd
若接收方窗口大小为0,主机A继续发送只有1个字节数据的报文段,若接收方确认,则缓存开始情况,并且确认报文将包含一个非0的rwnd;

3.5.6 TCP连接管理(🌟🌟🌟🌟🌟)

TCP三次握手

在这里插入图片描述

TCP协议中,主动发起请求的一端称为客户端,被动连接的一端称为服务端。不管是客户端还是服务端,TCP连接建立完后都能发送和接收数据。

起初,服务器和客户端都为CLOSED状态。在通信开始前,双方都得创建各自的传输控制块(TCB);服务器创建完TCB后遍进入LISTEN状态,此时准备接收客户端发来的连接请求:为了创建TCP连接,两台主机之间发送了3个分组,所以这种连接的创建过程被称为3次握手🤝;

第一次握手:客户端TCP首先向服务端TCP发送连接请求报文段。该报文(SYN报文段)不含应用层数据,但是报文段首部中一个标志位SYN比特被置为1,ACK=0;另外,客户随机选择初始序号(client_isn),并放在该报文段的序号字段。请求发送后,客户端便进入SYN-SENT状态。
⚠️注意:1)SYN=1,seq=client_isn,ACK=0;2)TCP规定:SYN=1的报文段不能有数据部分,但要消耗掉一个序号;

第二次握手:一旦包含TCP SYN报文段的IP数据报到达服务器主机,服务器将从中提取TCP SYN报文段,为该TCP连接分配TCP缓存和变量,并向该客户TCP发送允许连接的报文段;报文段首部包含:1)SYN=1;2)TCP报文段首部确认号字段被置为client_isn+1;3)服务器选择自己的初始序号(server_isn),并放在TCP报文段首部的序号字段中;该允许连接的报文被称为SYNACK报文段,发送完成后便进入SYN-RCVD状态。
⚠️注意:1)SYN=1,seq=server_isn,ack=client_isn+1,ACK=1;
2)ack=client_isn+1表示服务端希望下一个数据报发送序号从client_isn+1开始的字节;

第三次握手:收到SYNACK报文段后,客户也要给该连接分配缓存和变量;客户主机则向服务器发送另外一个报文段,表示对最后一个报文段对服务器的允许连接的报文的确认(通过将server_isn+1放在TCP报文段首部确认字段来完成);因**连接已经建立,SYN=0;该报文段首部的seq=client_isn+1,server_isn+1,ACK=1;客户端发完这个报文段后便进入ESTABLISHED状态,服务端收到这个应答后也进入ESTABLISHED状态,此时连接的建立完成!
⚠️注意:第三次握手可以在报文段负载中携带客户到服务器的数据了!

连接的建立为什么需要三次握手,而不是两次握手?

防止失效的连接请求报文段被服务端接收,从而产生错误。
失效的连接请求:若客户端向服务端发送的连接请求丢失,客户端等待应答超时后就会再次发送连接请求,此时,上一个连接请求就是『失效的』。

若建立连接只需两次握手,客户端并没有太大的变化,仍然需要获得服务端的应答后才进入ESTABLISHED状态,而服务端在收到连接请求后就进入ESTABLISHED状态。此时如果网络拥塞,客户端发送的连接请求迟迟到不了服务端,客户端便超时重发请求,如果服务端正确接收并确认应答,双方便开始通信,通信结束后释放连接。此时,如果那个失效的连接请求抵达了服务端,由于只有两次握手,服务端收到请求就会进入ESTABLISHED状态,等待发送数据或主动发送数据。但此时的客户端早已进入CLOSED状态,服务端将会一直等待下去,这样浪费服务端连接资源。

TCP连接的释放的四次挥手:

TCP连接的释放一共需要四步,因此称为四次挥手;因为TCP连接是全双工的,因此在四次挥手中,前两次挥手用于断开一个方向的连接后两次挥手用于断开另一方向的连接

第一次挥手:当client没有数据要发送给server了,他会给server发送一个FIN报文,告诉server:“我已经没有数据要发给你了,但是你要是还想给我发数据的话,你就接着发,但是你得告诉我你收到我的关闭信息了”,这是第一次挥手,挥手之后client进入FIN_WAIT_1的第一阶段;

第二次挥手:当server收到client发来的FIN报文后,告诉client:“我收到你的FIN消息了,但是你等我发完的”此时给client返回一个ACK信息,并且呢ack=seq+1,这是第二次挥手,挥手之后呢server进入CLOSE_WAIT阶段,而client收到之后处于FIN_WAIT_2第二阶段;

第三次挥手:当server发完所有数据时,他会给client发送一个FIN报文,告诉client说“我传完数据了,现在要关闭连接了”,然后呢server变成LAST_ACK状态,等着client最后的ACK信息,这是第三次挥手;

第四次挥手:当client收到这个FIN报文时,他会对这个消息进行确认,即给server发ACK信息,但是它不相信网络,怕server收不到信息,它会进入TIME_WAIT状态,万一server没收到ACK消息它可以可以重传,而当server收到这个ACK信息后,就正式关闭了TCP连接,处于CLOSED状态,而client等待了2MSL这样长时间后还没等到消息,它知道server已经关闭连接了,于是乎他自己也断开了,这是第四次挥手,这样TCP连接就断开了;

在这里插入图片描述

3.6、拥塞控制原理

3.6.1 拥塞原因与代价

计算机网络拥塞的原因是因为网络中的分组太多,而链路带宽和路由器缓存容量都是有限的

  • 当分组的到达速率接近链路容量时,分组将经历巨大的排队时延
  • 发送方必须执行重传已补偿因为缓存溢出而丢弃的分组;
  • 发送方遇到大的时延时所进行的不必要重传会引起路由器利用其链路带宽来转发不必要的分组副本;
  • 当一个分组沿着一条路径被丢弃时,每个上游路由器用于转发该分组到丢弃该分组而使用的传输容量最终被浪费掉了;

3.6.2 拥塞控制方法

拥塞控制:拥塞控制是作用于网络的,它是防止过多的数据注入到网络中,避免出现网络负载过大的情况;

流量控制:流量控制是作用于接收者的,它是控制发送者的发送速度从而使接收者来得及接收。

总体来说,我们可以更具网络层是否为传输层拥塞控制提供了显式帮助来区分拥塞控制方法:端到端拥塞控制网络辅助拥塞控制

端到端拥塞控制方法中,网络层并没有向传输层拥塞控制提供显式支持,即便网络中存在拥塞,端系统也必须通过对网络行为的观察(如分组丢失与时延)来判断;TCP必须通过端到端的方法解决拥塞控制,因为IP层不会像端系统提供有关网络拥塞的反馈信息。TCP报文段的丢失(超时或者收到3次冗余确认而得知)被认为是网络拥塞的一个迹象,TCP将相应地减小窗口长度

网络辅助的拥塞控制方法里,网络层会向发送方提供关于网络中拥塞状态的显式反馈消息;比如使用一个比特位来指示网络是否拥塞;拥塞信息从网络反馈到发送方一般有两种方式,其中直接反馈信息可以由网络路由器发送给发送方,这种方式的通知通常采用一种拥塞分组的形式;第二种形式的通知是路由器标记或者更新从发送方到接收方的分组中的某个字段来指示拥塞的产生,然后由接收方向发送方通知该网络发生了拥塞。

3.7、TCP拥塞控制

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值