TCP/IP协议族(第4版) 第13章 试读

 

  第三部分        运 输 层
13 章 运输层简介  313
14 章 用户数据报协议( UDP )  347
15 章 传输控制协议( TCP )  363
16 章 流控制传输协议( SCTP ) 
 
 
 
 
 
章讨论运输层协议能够提供的总体服务以及与这些服务相关的内容。本章还要描述针对不同状况而设计的一些通用运输层协议的行为。在后面几章的内容中,我们将会看到这些通用协议如何组合以建立诸如 UDP TCP 以及 SCTP 这样的 TCP/IP 协议族运输层协议。
目标
本章有以下几个目标:
q q定义运输层的进程到进程的通信,并与网络层的主机到主机的通信进行比较。
q q讨论运输层的编址机制,讨论端口号,定义不同用途的端口号范围的划分。
q q解释运输层的分组化问题:报文的封装和解封。
q q讨论运输层提供的复用(多到一)和分用(一到多)服务。
q q讨论流量控制以及它在运输层是如何实现的。
q q讨论拥塞控制以及它在运输层是如何实现的。
q q讨论运输层的无连接服务和面向连接的服务,并通过有限状态机( FSM)来说明它们的实现。
q q讨论四个通用运输层协议的行为以及它们的应用:简单协议、停止等待协议、返回 N协议和选择重传协议。
q q描述运输层利用捎带方式实现双向通信的思想。
正如我们在第2章中讨论的,运输层位于网络层和应用层之间。运输层负责向应用层提供服务,同时它接受来自网络层的服务。在本小节中,我们要讨论运输层能够提供的服务,而在下一小节,我们将讨论几个运输层协议背后的原理。
13.1.1 进程到进程的通信
运输层协议的首要任务是提供 进程到进程的通信( process-to-process communication 。进程是指使用了运输层服务的一个应用层实体(正在运行的程序)。在我们讨论进程到进程的通信是怎样实现的之前,先要了解一下主机到主机的通信和进程到进程的通信之间的区别。
网络层负责计算机级的通信(主机到主机的通信)。网络层协议只能把报文交付给目的计算机,但这还不算是完整的交付,报文必须要交付到正确的进程,而这正是运输层协议所要做的事。运输层协议负责把报文交付给合适的进程。图13.1所示为网络层和运输层的作用范围。
图13.1 网络层与运输层的比较
13.1.2 编址:端口号
虽然要完成进程到进程的通信可以有很多方法,但最常用的方法是通过 客户 服务器范式 client-server paradigm )(参见第 17 章)。位于本地主机上的进程称为 客户, 通常需要远程主机上的一个称为 服务器 的进程所提供的服务
这两个进程(客户和服务器)应当具有相同的名称。例如,若要获取远程主机上的日期和时间,我们需要在本地主机上运行一个叫做Daytime的客户进程,同时在远程主机上也运行着一个称为Daytime的服务器进程。
但是,今天的操作系统都支持多用户和多程序运行的环境。一个远程计算机在同一时刻可运行多个服务器程序,正如本地计算机可在同一时刻运行一个或多个客户程序一样。对通信来说,我们必须定义:
q q本地主机
q q本地进程
q q远程主机
q q远程进程
本地主机和远程主机都是通过IP地址来定义的。要定义进程,我们需要第二种标识,称为端口号(port numbers)。在TCP/IP协议族中,端口号是0~65535之间的整数。
客户程序通过一个端口号来定义自己,这种端口号称为临时端口号(ephemeral port number)。“临时”这个词的含义是指生存时间较短,之所以用这个词是因为客户的生存时间通常都比较短。建议为临时端口号取一个大于1023的整数,这样可使一些客户/服务器程序能正常工作。
服务器进程也必须用一个端口号来定义自己。但是这个端口号不能随机选取。如果在服务器端的计算机上运行的服务器程序被指派了一个随机数作为其端口号,那么客户端的进程就是想要访问这个服务器并使用它的服务也无法掌握它的端口号。当然,一种可能的解决办法是发送一个特别的分组,以请求得到某个特定服务器的端口号,但这就需要更多的额外开销。TCP/IP决定让服务器使用全球通用端口号,它们称为熟知端口号(well-known port numbers)。对这个规则也有一些例外情况。例如,有的客户也被指派了熟知端口号。每个客户进程都知道相应的服务器进 程的熟知端口号。例如,上面讨论过的 Daytime 客户进程可使用临时端口号 52000来标识自己,但Daytime服务器进程则必须使用熟知(永久的)端口号13。图13.2描绘了这一概念。
图13.2 端口号

 

图13.3 IP地址与端口号之对比
 
 
现在应当很清楚了,在选择数据最后的终点时,IP地址和端口号起着不同的作用。目的IP地址定义了全世界无数台主机之中的某一台主机,而当这台主机被选定后,端口号则定义了在这台特定主机上运行的多个进程之中的某一个(见图13.3)。

 

ICANN定义的范围段
ICANN 把端口号划分为三个范围段:熟知的、注册的和动态(或专用)的,如图 13.4 所示。
q q熟知端口 范围从0~1023的端口由ICANN指派和控制,这些都是熟知端口。
q q注册端口 范围从1024~49151的端口,ICANN既不指派也不控制,但它们必须在ICANN处注册以防止重复。
图13.4 ICANN定义的范围段
q q动态端口 范围从49152~65535的端口既不用指派也不用注册。它们可被用作临时的或专用的端口号。最初的建议是客户使用的临时端口号应当在这个范围之内选择。但是,大多数系统并没有遵循这个建议。
熟知端口号小于1024。
13.1
在UNIX中,熟知端口被保存在/etc/services文件中。这个文件中的每一行给出了一个服务器名及其熟知端口号。我们可以通过实用程序grep把我们想要的应用所对应的那一行提取出来。下面给出了TFTP的端口。请注意,TFTP在UDP和TCP中都可以使用端口69。SNMP(参见24章)使用了两个端口号(161和162),各有不同的用途。
 
$grep   tftp  /etc/services
tftp      69/tcp
tftp      69/udp
 
$grep   snmp/etc/services
snmp        161/tcp          #Simple Net Mgmt Proto
snmp        161/udp           #Simple Net Mgmt Proto
snmp        162/udp           #Traps for SNMP
 
套接字地址

 

图13.5 套接字地址
 
TCP协议族的运输层协议在建立连接时,需要在连接的两端同时使用IP地址和端口号。IP地址和端口号的组合就称为套接字地址(socket address)。客户套接字地址唯一地定义了一个客户进程,正如服务器套接字地址唯一地定义了一个服务器进程一样(见图13.5)。

 

要在因特网中使用运输层的服务,我们需要有一对套接字地址:客户套接字地址和服务器套接字地址。这四个信息是网络层分组首部和运输层分组首部中的一部分。前一个首部中包含了IP地址,而后一个首部中则包含了端口号。
13.1.3 封装和解封
为了把报文从一个进程发送到另一个进程,运输层协议要对报文进行封装和解封(参见图13.6)。
图13.6 封装和解封
封装发生在发送方。当进程想要发送一个报文时,就把这个报文递交给运输层,随之一起递交的还包括一对套接字地址和其他一些信息,其具体内容取决于运输层协议。运输层接收数据并为之添加运输层首部。在因特网中,运输层的分组也称为用户数据报、数据段或分组。在本章我们称之为分组。
解封发生在接收方。当报文到达目的运输层后,首部被拆除,然后运输层将报文交付给在应用层运行的进程。如果接收方需要对收到的报文进行响应,那么发送方的套接字地址也要一起递交给该进程。
13.1.4 复用和分用
当一个实体接受来自多个源的输入时,就称为复用(multiplexing)(多到一),而当一个实体将数据交付到多个源时,就称为分用(demultiplexing)(一到多)。源点的运输层执行的是复用,而终点的运输层执行的是分用(参见图13.7)。
图13.7 复用和分用
图13.7描绘了一个客户和两个服务器之间的通信。在客户端运行着三个进程:P1、P2和P3。客户进程P1和P3需要向某个服务器上运行的相应服务器进程发送请求,而客户进程P2则需要向另一台服务器上运行的相应服务器进程发送请求。客户端的运输层从这三个进程处接收到三个报文,并产生了三个分组,因此它起到复用器的作用。分组1和分组3使用相同的逻辑信道到达第一个服务器的运输层。当它们到达该服务器后,运输层就担负起分用器的作用,并将报文分别交付给两个不同的进程。在第二个服务器上的运输层接收到分组2并将它交付给相应的进程。
13.1.5  流量控制
当一个实体产生数据而另一个实体消耗这些数据时,数据的产生速度和消耗速度之间应当达到某种平衡。如果数据产生的速度比消耗的速度快,那么消耗方就会因来不及处理而被迫丢弃一些数据。如果数据产生的速度比消耗的速度慢,消耗方就需要等待,从而使得整个系统的效率降低。流量控制与前面所提到的第一个问题有关。我们需要防止的是发生在消耗端的数据丢失。
推送或拉取
从生产者到消耗者的数据交付可以通过两种方式完成:推送或者拉取。如果发送方只要数据一产生就发送出去,不管消耗方之前是否请求过这些数据,这样的交付方式就称为推送。如果发送方只有在消耗方请求之后才发送这些数据,那么这样的交付方式就称为拉取。图13.8所示为这两种类型的交付。
图13.8 推送或拉取
当生产者推送数据时,消耗者可能会因数据太多而来不及处理,所以就需要在反方向上进行流量控制,以防止数据被丢弃。换言之,消耗者需要警告生产者停止发送数据,并在它再次准备好接收时,再向生产者发出通知。当消耗者拉取数据时,它是在自己准备好的情况下才会提出请求,因而此时不需要流量控制。
运输层的流量控制
在运输层的通信中,我们需要与四个实体打交道:发送方进程、发送方运输层、接收方运输层和接收方进程。应用层的发送进程仅仅是一个生产者。它产生报文块并将其推送到运输层。发送方的运输层要扮演两个角色:它既是消耗者也是生产者。它要消耗被生产者推送过来的报文,同时还要将这些报文封装成分组,并推送给接收方的运输层。接收方的运输层也要扮演两个角色:它既是消耗者,因为它要消耗来自发送方的报文,也是生产者,因为它要将报文解封后交付到应用层。不过,最后的交付通常是一种拉取交付,也就是说运输层会等待应用层的进程过来索取这些报文。
从图13.9中可以看出我们至少需要两种情况下的流量控制:从发送方的运输层到发送方的应用层以及从接收方的运输层到发送方的运输层。
图13.9 运输层的流量控制
缓存
虽然流量控制可以用多种方法实现,但最常见的一种解决方法是使用两个缓存。一个位于发送方的运输层,而另一个位于接收方的运输层。此处的缓存是指可以在发送方和接收方用来保存分组的一组存储器。而对于流量控制的通信则可以通过从消耗者向生产者发送信号来实现。
当发送方的运输层缓存满溢时,它就通知应用层停止传递报文块,而当它又有了空位置时,就通知应用层可以再次传递报文块了。
当接收方的运输层缓存满溢时,它就通知发送方的运输层停止发送分组,而当它又有了空位置时,就通知发送方的运输层可以再次发送分组了。
13.2
前面的讨论要求消耗者和生产者在以下两种情况都要进行通信联系:当缓存满溢时和当缓存又有了空位置时。如果使用的缓存只有一个位置,那么通信就会变得很简单。假设这两个运输层都使用了只能存放一个分组的存储空间。当发送方运输层中的这个存储位置空闲时,发送方运输层就提醒应用层可以发送下一个报文块。当接收方运输层中的这个存储位置空闲时,它就向发送方的运输层发送一个确认,使之发送下一个分组。正如我们在后面将会看到的,像这种在发送方和接收方都只使用了一个存储位置的流量控制的效率是非常低的。
13.1.6  差错控制
在因特网中,因为负责从发送方运输层向接收方运输层运送分组的网络层(IP)是不可靠的,所以,如果应用程序要求可靠性,那么我们就必须让运输层变得可靠。可以通过在运输层中加入差错控制来实现其可靠性。运输层的差错控制负责:
1.检测并丢弃损坏的分组。
2.跟踪丢失和丢弃的分组并重传它们。
3.识别重复的分组并丢弃它们。
4.保存失序到达的分组,直至缺失的分组全部抵达。
差错控制不像流量控制,它只涉及到发送方的运输层和接收方的运输层,因为我们假设在应用层和运输层之间的报文块交换是无差错的。图13.10描绘了发送方和接收方的运输层之间的差错控制。与流量控制一样,在大多数时间都是由接收方的运输层来管理差错控制,它会通知发送方的运输层出现了什么问题。
图13.10 运输层的差错控制
序号
差错控制要求发送方的运输层知道哪个分组应当被重传,而接收方的运输层则要了解哪个分组是重复的,或者哪个分组失序到达。如果给分组编了号,那么就能够做到这一点。我们可以在运输层分组的首部中增加一个字段,以保存分组的 序号 sequence number )。当一个分组损坏或丢失时,接收方的运输层通过这个序号就能够以某种方式通知发送方的运输层重传该分组。同时,如果接收到的两个分组具有相同的序号,接收方的运输层也能够检测出这是两个重复的分组。通过观察序号的连续性还能识别出失序到达的分组。
分组被顺序地编号。不过,由于我们需要把这个序号包含在每个分组的首部中,因而不得不加以限制。如果分组的首部中有 m位用于序号,那么这个序号的范围就是从0到2 m  − 1。例如,如果 m是4,那么序号就只能是在0到15之间。但是我们可以回过头来重新使用序号,因此在这种情况下的序号就是
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,…
换言之,序号是模2 m的。
对于差错控制,序号是模2 m的,其中 m是序号字段的位数。
确认
我们可以用正信号或者负信号来实现差错控制。只要一个或一组分组安全且完好地到达了,那么接收方就可以为它们发送一个确认(ACK)。另一方面,接收方可以简单地丢弃损坏的分组,发送方如果使用了计时器,就能够检测出这些丢失的分组。在发送分组时,发送方要启动一个计时器,如果该计时器到期了,而发送方还没有收到相应的ACK,那么它就要重传这个分组。重复的分组可以被接收方悄无声息地丢弃掉,而失序到达的分组可以被丢弃(对发送方来说就好像是这个分组丢失了),也可以被保存起来,直到缺失的分组全部抵达为止。
13.1.7 流量控制和差错控制的组合
我们曾经讨论过,流量控制要求使用两个缓存,一个在发送方,另一个在接收方。我们也说过,差错控制要求双方使用序号和确认号。如果我们使用了两个带编号的缓存,一个在发送方,另一个在接收方,那么这两个需求就可以合二为一。
在发送方,当为分组的发送而做准备时,可以使用缓存中下一个空位的编号 x作为该分组的序号。当该分组被发送时,它的一个副本就保存在该存储器中的 x位置上,直至收到来自另一端的确认。当与已发送分组相关的确认到达时,存储器中该分组的副本就被清除,从而使该存储位置变为空闲。
在接收方,当序号 y的分组到达时,就将其保存在存储器的 y位置上,直到应用层准备好接收它,同时可以发送一个确认以声明分组 y已经到达。
滑动窗口
因为序号是模2 m的,所以从0至2 m − 1的序号可以表示为一个环(图13.11)。
缓存被表示为一组小格子,称为滑动窗口(sliding window),在任何时候它们都占据了圆的一部分。在发送方,当一个分组被发送出去,相应的小片就被标记。当所有的小片都被标记后,就表示缓存已满,不允许从应用层接收更多的报文。当一个确认到达后,相应小片的标记就被取消。如果这个窗口前端连续多个小片都没有标记,那么这个窗口就向后滑动到相应的序号范围上,以允许窗口后端有更多空闲的小片。图13.11描绘了发送方的滑动窗口。序号是模16( m = 4)的,且窗口大小为7。请注意,滑动窗口只不过是一种抽象,而实际上它是通过计算机变量来保存下一个将要发送的分组的编号以及刚刚发送出去的最后一个分组的编号来实现的。
图13.11 用圆形表示的滑动窗口
大多数协议使用条形来表示滑动窗口。其思想完全一样,只不过通常这样做可以节约纸张空间。图13.12所示为条形表示法。这两张图告诉我们的是同一回事。如果我们捏住图13.12中各部分的两端分别向上弯曲,就可以得到如图13.11一模一样的图了。
图13.12 用条形表示的滑动窗口
13.1.8 拥塞控制
因特网中存在的一个重要的问题是拥塞(congestion)。如果一个网络中的负载(load)(也就是发送到网络上的分组数量)大于网络的容量(也就是网络能够处理的分组数量),这个网络就有可能发生拥塞。拥塞控制(congestion control)指的是用来控制拥塞,以使负载保持低于容量的机制和技术。
我们可能会问为什么网络中会出现拥塞?只要是涉及到等待的系统都会发生拥塞。例如,任何因车流中发生了意外情况而导致的堵车都是高速公路上出现拥塞的原因,比如说在上下班高峰时间发生了车祸。
网络或者互联网中的拥塞是由于路由器或交换机中有一些队列,也就是在分组被处理之前或之后用来保存这些分组的缓存。分组被放入合适的外出队列并等待轮到自己被发送。这些队列空间是有限的,因此到达路由器的分组数量有可能会大于路由器能够保存的分组数量。
拥塞控制指的是能够在拥塞发生之前预防它,或者在拥塞发生之后消除它的技术和机制
开环拥塞控制
在拥塞发生之前使用一些策略来预防拥塞称为开环拥塞控制(open-loop congestion control)。在此类机制中,拥塞控制可以由源点也可以由终点来处理。
重传策略 有时重传是不可避免的。如果发送方觉得一个发送出去的分组丢失或损坏了,那么这个分组就需要重传。一般来说,重传可能会加重网络的拥塞。但是,好的重传策略可以预防拥塞。这就需要将重传策略以及重传计时器设计得能够优化效率,同时还能够预防拥塞。
窗口策略 发送方窗口的类型也可能会影响到拥塞。我们将在本章稍后看到对于拥塞控制来说选择重传窗口就要比返回 N窗口好。
确认策略 由接收方实施的确认策略也有可能会影响拥塞。如果接收方不是对每一个收到的分组都进行确认,那么也能够使发送方放慢发送速率,因而有助于预防拥塞。在这种情况下可以使用几种方式。接收方可以仅仅在自己有分组要发送时,或者在一个特殊的计时器到期时才发送一个确认。接收方也可以决定一次为 N个分组发送确认。要知道这些确认也是网络负担的一部分。发送的确认越少,给网络带来的负担也越轻。
闭环拥塞控制
闭环拥塞控制(closed-loop congestion control)机制试图在拥塞发生后缓解拥塞的程度。有几个此类机制已经被用在不同的协议中。我们要描述的是在运输层中使用的机制。发送方的窗口大小可以是灵活的。决定发送方窗口大小的一个因素就是因特网的拥塞状况。发送方的运输层可以通过观察分组的丢失情况来监视因特网的拥塞状况,如果拥塞状况恶化,就用一种策略来减小窗口大小,反之亦然。我们将在第15章中看到TCP是如何使用这种策略来控制它的窗口大小的。
13.1.9 无连接的和面向连接的服务
像网络层协议一样,运输层协议也可以提供两种类型的服务:无连接的服务和面向连接的服务。不过这两种服务在本质上与网络层的不同。在网络层,无连接的服务意味着属于同一报文的多个数据报采取了不同的路径。而在运输层,我们并不关心分组采取什么物理路径(我们假设在两个运输层之间有一条逻辑连接),运输层的无连接服务表示分组和分组之间是互相独立的,而面向连接的服务则意味着它们相互之间有联系。让我们来详细说明这两种服务。
无连接的服务
在使用无连接的服务时,源进程(应用程序)需要将它的报文分割成大小可被运输层接受的数据块,并将这些数据块逐个地交付到运输层。运输层视这些数据块为独立的数据单元,块和块之间没有联系。当来自应用层的一个数据块到达后,运输层就把它封装到一个分组中,然后发送这个分组。为了说明分组之间的独立性,假设客户进程有三个数据块要发送给服务器进程。这些数据块按顺序递交给无连接的运输协议。但是,因为在运输层这些分组之间是没有联系的,所以分组就有可能失序到达终点,并且同样失序地交付给服务器进程。在图13.13中,我们用时间线来说明这些分组的运动,但我们假设从进程到运输层的交付以及从运输层到进程的交付是即时的。
图13.13 无连接服务
如图所示,在客户端,有三个报文块被按序( 1 2 3 )递交给了客户运输层。因为第二个分组在传输时有额外的时延,所以在服务器端,这些报文并没有按序交付( 1 3 2 )。如果这三个数据块属于同一个报文,那么这个服务器收到的就有可能是一个奇怪的报文。
如果其中的一个报文丢失了,情况会更加糟糕。因为分组上没有编号,接收方运输层无法知道有一个分组已经丢失了。它只能向服务器进程交付两个数据块。
之所以会出现以上的问题,是因为这两个运输层彼此之间没有协调一致。接收方运输层既不知道什么时候第一个分组到达,也不知道什么时候所有的分组全部到齐。
我们可以说在无连接服务的情况下,没有哪种流量控制、差错控制或拥塞控制策略能够有效实施。
面向连接的服务
在使用面向连接的服务时,客户和服务器首先要在它们之间建立一条连接。数据的交换只能是在连接建立之后发生。在数据交换完成后,该连接需要被拆除(图 13.14 )。正如我们在前面提到的,运输层面向连接的服务与网络层面向连接的服务有所不同。在网络层,面向连接的服务意味着两端的主机及其中间的路由器之间的协调一致。而在运输层,面向连接的服务仅涉及两个主机,也就是说服务是端对端的。这就意味着,不管是无连接的网络层协议,还是面向连接的网络层协议,我们都能在上面使用面向连接的运输层协议。图 13.14 描绘的是运输层的面向连接服务的连接建立、数据传送以及拆除连接这几个阶段。请注意,大多数协议将连接建立阶段中的第三个和第四个分组合并成一个分组,我们将会在第 15 章和第 16 章中了解到。
我们能够在面向连接的协议中实施流量控制、差错控制和拥塞控制。
有限状态机
不管是提供无连接的服务,还是面向连接的服务,一个运输层协议的行为可以很好地用一个有限状态机(finite state machine,FSM)来表示。图13.15就是用FSM表示的运输层协议。使用这个工具,各运输层(发送方或接收方)都可以被认为是一个具有有限状态的机器。有限状态机总是处在某一种状态中,直到有一个事件发生。对每个事件的响应有两种:定义要执行的动作列表(可能为空),并决定下一个状态(也可能与当前状态相同)。在这些状态之中必须有一个是开始状态,也就是这个有限状态机一开机就进入的状态。在图中我们用圆角框表示状态,用黑体字(带颜色的文本)表示事件,用普通字体表示动作。开始状态有一个不来自其他状态的进入箭头。一条水平线用于分隔事件和动作,而在第15章中我们将用斜线来代替水平线。箭头方向表示向下一个状态的运动方向。
图13.14 面向连接的服务
我们可以把无连接的运输层视为只有一个状态的FSM。这个有限状态机的两端(客户和服务器)永远处于建立的状态,总是准备好发送和接收运输层的分组。
另一方面,在面向连接的运输层FSM中,到达建立的状态之前需要经过三个状态。而在关闭连接之前也需要经过三个状态。在没有连接时,有限状态机一直处于Closed状态。状态机保持此状态直至本地进程的打开连接请求到达,于是状态机就向远程运输层发送一个打开请求分组,并且进入Open-wait-I状态中。当收到来自另一端的确认时,本地FSM进入Open-wait-II状态。当状态机在此状态时,一条单向连接就已经建立好了,但是如果需要双向连接,那么状态机还要在这个状态继续等待,直至另一端也请求了连接。当收到这个请求后,状态机发送确认并进入Established状态。
当双方都处在建立的状态时就可以互相交换数据以及对数据的确认了。但是我们要记住,不管是在无连接的还是面向连接的运输层协议中,建立的状态本身就代表了一组数据传送状态,我们将在下一节讨论运输层协议时讨论到。
图13.15 用FSM来表示无连接的服务和面向连接的服务
要拆除一个连接,应用层向本地运输层发送关闭请求报文。运输层就向另一端发送关闭请求分组,并进入 Close-wait-I 状态。收到来自另一端的确认后,机器进入 Close-wait-II 状态, 并等待对方发来的关闭请求分组。当这个分组到达后,状态机发送一个确认并进入 Closed 状态。
面向连接的FSM有几种不同的变体,我们将在第15章和第16章中再讨论。在第15和16章中,我们还要讨论如何压缩或扩展这个FSM,且状态的名称也会有所变化。
把我们前面所描述的一系列服务组合起来就能够创建一个运输层协议。为了更好地理解这些协议的行为,我们先从最简单的协议开始谈起,再逐渐增加复杂度。TCP/IP协议使用的运输层协议或者是对这些协议之一的改进,或者是它们的组合。这也是我们在本章要讨论这些协议的原因,就是为更好地理解接下来三章内容所介绍的比较复杂的协议铺平道路。为了简化讨论,对于所有这些协议,我们一开始都认为是数据分组只向一个方向传送的单向协议(即单工的)。在本章结尾,我们会简单地讨论如何将它们变成数据分组可以在两个方向同时传送的双向协议(即全双工)。
13.2.1  简单协议
我们的第一个协议是一个简单的无连接协议,它既没有流量控制,也没有差错控制。我们假设接收方能够即时处理它收到的任何分组。换言之,接收方永远不会因为涌入的分组太多而处理不过来。图13.16所示为这个协议的概要图。
图13.16 简单协议
发送方的运输层从应用层那里得到一个报文,用它产生一个分组,然后发送这个分组。接收方的运输层从网络层那里收到一个分组,从分组中提取出该报文,然后将该报文交付给应用层。发送方和接收方的运输层为它们各自的应用层提供传输服务。
FSM
在发送方的应用层有报文要发送之前,发送方不可能发送分组。在分组到**前,接收方也不可能向应用层交付报文。我们可以用两个FSM来表示这些要求。每个FSM只有一个状态,即准备好状态。发送方状态机一直保持在准备好状态,直至应用层的进程有一个请求到来。当这个事件发生后,发送方状态机将报文封装成一个分组,并把这个分组发送给接收方状态机。接收方状态机也总是保持在准备好状态,直至来自发送方状态机的分组到达。当这个事件发生后,接收方状态机把收到的分组解封后提取出该报文,并把它交付给应用层的相应进程。图13.17所示为这个简单协议的FSM。我们将在第14章中看到,UDP协议就在这个协议的基础上做了一些改进。
图13.17 简单协议的FSM
简单协议是一个无连接协议,既没有流量控制,也没有差错控制。
13.3
图13.18所示为使用这个协议进行通信的一个例子。它非常简单。发送方一个接一个地发送分组,甚至根本不用考虑接收方。
图13.18 例13.3的流程图
13.2.2 停止等待协议
我们的第二个协议是面向连接的协议,称为 停止等待协议 Stop-and-Wait protocol ),它使用了流量控制和差错控制。发送方和接收方都使用了大小为 1 的滑动窗口。发送方一次发送一个分组,然后在发送下一个分组之前要先等待一个确认。为了检测损坏的分组,我们需要在每个数据分组中增加一个检验和,并在分组到达接收方后检查它。如果检验和不正确,就说明分组损坏了,这个分组被悄无声息地丢弃掉。接收方的沉默对发送方来说就是一个信号,说明分组不是损坏了就是丢失了。发送方在每发送一个分组时要启动一个计时器。如果在计时器到期之前确认到达了,计时器就停止计时,发送方继续发送下一个分组(如果它还有分组要发送的话)。如果该计时器超时,那么发送方就假定分组丢失或者损坏了,因而重传前一个分组。这就意味着发送方需要保存分组的副本直至它的确认到达为止。图 13.19 所示为停止等待协议的概要图。请注意,在任何时候信道中都只有一个分组和一个确认。
图13.19 停止等待协议
停止等待协议是一种面向连接的协议,它提供了流量控制和差错控制。
在停止等待协议中,流量控制通过迫使发送方等待确认来实现,差错控制通过丢弃损坏的分组并让发送方在计时器超时后重传未确认的分组来实现。
序号
为了防止重复的分组,协议使用了序号和确认号。分组的首部要增加一个字段用来保存分组的序号。序号的范围是需要慎重考虑的。因为我们希望分组的长度最小化,所以我们寻求的是不会混淆通信的最小范围。让我们来推算一下所需的序号范围。假设我们使用 x作为一个序号,那么此后只要用到 x + 1就够了,没有必要使用 x + 2。为了说明这个问题,我们假设发送方发送了一个序号为 x的分组,可能会发生以下三种情况:
1.分组安全完好地抵达接收方。接收方发送一个确认。这个确认到达发送方,使发送方继续发送下一个序号为 x + 1的分组。
2.分组损坏或从未抵接收方。发送方在超时后重传这个分组(序号为 x),接收方返回一个确认。
3.分组安全完好地抵达接收方。接收方发送一个确认,但是这个确认损坏或丢失了。发送方在超时后重传这个分组(序号为 x)。注意此时这个分组是重复的。接收方能够识别出这种重复,因为它希望接收的分组是 x + 1,但实际接收到的分组却是 x
我们可以看出序号 xx + 1都是必要的,因为接收方需要用它们来区分情况1和情况3。但是分组没有必要使用序号 x + 2。在情况1中,分组可以再次使用序号 x,因为分组 x x + 1 都已经被确认了,发送方和接收方也没有什么弄不清楚的地方。在情况 2 和情况 3 中,新的分组是 x + 1,不是 x + 2。如果仅仅需要 xx + 1,那么我们可以让 x = 0且 x + 1 = 1。也就是说该序号是0,1,0,1,0…。这被称为模2运算(译注:通常记为mod 2)。
在停止等待协议中,我们可以使用1位字段来为分组编号。这个序号基于模2运算。
确认号
因为序号必须既适合数据分组,又适合确认,所以我们有以下约定:确认号总是声明了接收方 准备接收的下一个分组 的序号。例如,如果分组 0 已经安全完好地抵达了,那么接收方就发送一个确认号为 1 ACK (表示下一个希望接收分组 1 )。如果分组 1 安全完好地抵达了,那么接收方就发送一个确认号为 0 ACK (表示下一个希望接收分组 0 )。
在停止等待协议中,确认号总是声明了模2运算的下一个希望接收的分组序号。
发送方有一个控制变量,我们称之为 S(sender),它指向发送窗口中唯一的空格。接收方也有一个控制变量,我们称之为 R(receiver),它指向接收窗口中唯一的空格。
在停止等待协议中,所有的计算都是模2的。
FSM
图13.20描绘了停止等待协议的FSM。因为这个协议是面向连接的,所以在交换数据分组前,连接的两端都应当处于建立的状态。我们在这里所描绘的状态实际上都是包含在建立的状态中的子状态。
图13.20 停止等待协议的FSM
发送方 发送方在一开始时处于准备好状态,但是它可以在准备好和阻塞这两个状态之间变换。变量 S的值初始化为0。
q q准备好状态 当发送方处于此状态时,它仅等待一个事件的发生。如果来自应用层的请求到达了,发送方就产生一个序号设为 S的分组。这个分组的一个副本被保存起来,而这个分组被发送出去。发送方启动唯一的计时器,然后进入到阻塞状态。
q q阻塞状态  当发送方处于此状态时,可能会发生的事件有三个:
1 .如果一个无差错的 ACK 到达,且它的确认号指向下一个要发送分组,也就是说 ackNo = (S + 1) mod 2 ,那么计时器停止计时,窗口滑动使 S = (S + 1) mod2 。最后发送方进入准备好状态。
2.如果一个损坏的ACK到达,或者虽无差错但ackNo ≠ ( S + 1) mod 2的ACK到达,这个ACK被丢弃。
3.如果计时器超时,发送方重新传送那个唯一的待确认分组,并重启计时器。
接收方 接收方总是在准备好状态。变量 R的初始值为0。有三个事件可能会发生:
1.如果一个seqNo = R的无差错分组到达,那么这个分组中的报文被交付给应用层。然后窗口滑动到 R = ( R + 1) mod 2,最后发送一个ackNo = R的ACK。
2.如果一个seqNo ≠ R的无差错分组到达,这个分组被丢弃,但是要发送ackNo = R的一个ACK。
3.如果一个损坏的分组到达,这个分组被丢弃。
13.4
图13.21所示为一个停止等待协议的例子。分组0被发送且确认。分组1丢失并在计时器超时后重传。重传的分组1被确认且计时器停止计时。分组0被发送且被确认,但是这个确认丢失了。发送方不知道丢失的是分组还是确认,因此在计时器超时后重传分组0,重传的分组0被确认。
图13.21 例13.4的流程图
效率
如果我们的信道又粗又长,那么停止等待协议是非常低效率的。所谓粗是指我们的信道有较大的带宽(高数据率),而所谓长是指往返时延较长。它们俩的乘积被称为带宽时延积(bandwidth-delay product)。我们可以把信道看成是一根管道,那么带宽时延积就是管道的容量,以比特为单位。管道一直放在那,如果我们不充分利用它,我们的效率就很低。带宽时延积是对发送方在等待接收方确认的同时能够通过系统传送的比特数的度量。
13.5
假设在一个停止等待系统中,线路带宽是1 Mbps,且1比特的往返时间是20毫秒。它的带宽时延积是多少?如果这个系统的数据分组长度是1000比特,这条线路的利用率是百分之几?
它的带宽时延积是比特。这个系统在数据从发送方到达接收方,再由接收方返回确认这一段时间内总共可以发送20000比特的数据。但是这个系统仅发送了1000比特的数据。我们可以认为利用率仅为1000/20000或5%。正是由于这个原因,对于带宽很大或时延很长的线路来说,使用停止等待协议非常浪费线路容量。
13.6
假如在例13.5中我们有一个协议能够一次最多发送15个分组,然后再停下来等待它们的确认,此时线路的利用率的百分比是多少?
它的带宽时延积仍然是20000比特。系统能够在一个往返时间内发送15个分组或者说15000比特。这就意味着利用率可以达到15000/20000或75%。当然,如果其中有损坏的分组,这个利用率会因为分组的重传而大大降低。
流水线方式
在组网或其他领域内,一个任务通常会在它的前一个任务结束之前就已经开始了,我们称之为流水线方式(pipelining)。在停止等待协议中不使用流水线方式,因为发送方必须等待前一个分组到达它的终点并被确认之后才能发送下一个分组。但是,在我们要介绍的下面两个协议中都使用了流水线方式,因为发送方在接收到对前几个分组的反馈之前还可以再发送几个分组。因为相对于固定的带宽时延积,传送的比特数量变大了,所以说流水线方式提高了传输的效率。
13.2.3  返回N协议
为了提高传输的效率(填满管道),在发送方等待确认时应当有多个分组正在传送中。换言之,我们需要让多个分组处于等待确认的状态,以便在发送方等待确认的同时,信道也能保持忙碌状态。在这一小节中,我们先来讨论一个能够达到此目标的协议,而在下一小节我们再来讨论第二个此类协议。第一个协议称为返回 N(Go-Back-N,GBN),这个名字的由来稍后就会弄清楚。返回 N协议的关键是我们在收到确认之前能够发送多个分组,但接收方只能缓存一个分组。发送方为发送出去的分组保存副本直至确认到达。图13.22所示为这个协议的概要图。请注意,在信道中同时可存在多个数据分组和确认。
图13.22 返回N协议
序号
我们在前面曾经说过序号必须是模2 m的,其中 m是序号字段的长度,以比特为单位。
返回 N协议中,序号必须是模2 m的,其中 m是序号字段的长度,以比特为单位。
确认号
在这个协议中,确认号是一个累计值,定义了下一个希望接收的分组的序号。例如,如果确认号(ackNo)是7,就表示一直到序号6之前的所有分组都已安全完好地到达了,并且接收方正在期盼的是序号为7的分组。
在返回 N协议中,确认号是一个累积值,定义了希望下一个到达的分组的序号。
发送窗口
发送窗口是一个想象的方框,它覆盖了正在传送的或可以传送的数据分组的序号。在这个窗口中,有些序号定义的是已经发送出去的分组,另一些则定义了可以被发送的分组。窗口的最大值是2 m − 1,原因我们稍后再讨论。在本章,我们令这个窗口大小固定,并设 置为最大值,但是我们将在后面的几章中看到,有一些协议可能使用可变的窗口大小。图13.23描绘了一个返回 N协议,其滑动窗口大小为7( m = 3)。
图13.23 返回N协议的发送窗口
发送窗口在任何时刻都将可能的序号划分为四段。第一段在窗口的左边,它定义的序号属于已经被确认的分组。发送方不再为这些分组操心,也不保存这些分组的副本。第二段用阴影表示,在这个范围内的序号是属于已经发送出去但目前状态未知的分组。发送方还需要等待才能知道这些分组是被收到了还是丢失了。我们称它们是 待确定 分组。第三段是窗口中的白色区域,它定义了允许发送的分组的序号,只不过相应的数据还没有从应用层传过来。最后的第四段在窗口的右边,它定义的是还不能使用的序号,除非窗口滑动过去才行。
窗口本身就是一个抽象,在任何时刻都要用三个变量来定义它的大小和位置。我们称这些变量为 Sf(发送窗口,第一个待确认的分组), Sn(发送窗口,下一个要发送的分组), S size(发送窗口,大小)。变量 Sf定义了第一个(最老的)待确认分组的序号。变量 Sn保存的是分配给下一个将要发送的分组的序号。最后,变量 S size定义了窗口大小,在我们的这个协议中是它固定的。
发送窗口是一个抽象化的概念,它定义了一个想象的方框,最大窗口为2 m − 1,且具有三个变量: Sf  SnS size
图13.24描绘了当从另一端传来的一个确认到达时,发送窗口如何向右滑动一格或多格。在图中,一个确认号为6的确认到达。这就表示接收方等待接收序号为6的分组。
当ackNo在 SfSn之间(采用模运算)的一个无差错的ACK到达后,发送窗口就向前滑动一格或多格。
图13.24 滑动发送窗口
接收窗口
接收窗口保证了正确的数据分组被接收,且正确的确认分组被发送。在返回 N协议中,接收窗口大小总是1。接收方总是在期待着某一个特定分组的到达。任何失序到达的分组都会被丢弃并重传。图13.25所示为接收窗口。请注意我们只需要一个变量 Rn(接收窗口,希望接收的下一个分组)来定义这个抽象窗口。窗口左边的序号属于已经接收且被确认的分组,窗口右边的序号定义的是不允许接收的分组。任何序号落在这两个区域中的分组都被丢弃。只有序号与 Rn的值相匹配的那一个分组才能被接收和确认。接收窗口也要滑动,但一次只滑动一格。当一个正确的分组被接收后,窗口就滑动到 Rn = ( Rn +1) mod 2 m
图13.25 返回N的接收窗口
接收窗口是一个抽象概念,定义了一个大小为1且只有一个变量 Rn的想象的方框。当一个正确的分组到达后,这个窗口就滑动,且一次只滑动一格。
计时器
虽然每个发送出去的分组都可以有一个计时器,但在我们的协议中总共只使用了一个计时器。原因是第一个待确认的分组总是会最先超时。当这个计时器超时后,我们就重传所有待确认的分组。
重传分组
当计时器超时后,发送方重传所有待确认的分组。例如,假设发送方已经发送了分组6( Sn = 7),但唯一的那个计时器超时了。如果 Sf = 3,那就是说分组3、4、5和6都尚未被确认,发送方返回到前面,重传分组3、4、5和6。这就是为什么这个协议叫做返回 N的原因。一旦超时,发送方就返回到 N位置并重传所有分组。
FSM
图13.26描绘了GBN协议的FSM。
图13.26 返回N协议的FSM
发送方 发送方开始处于准备好状态,但是它有可能进入两种状态之一:准备好状态和阻塞状态。通常两个变量初始化为0( Sf = Sn = 0),但在后面的几章中我们将会看到在TCP/IP协议族中有些协议使用了不同的初始值。
q q准备好状态 当发送方位于准备好状态时有四个事件可能会发生。
1.如果一个来自应用层的请求到达,发送方就产生一个序号置为 Sn的分组。这个分组的一个副本被保存起来,而这个分组被发送出去。若唯一的那个计时器未运行则启动计时器。现在 Sn的值递增到( Sn = Sn + 1) mod 2 m。如果窗口满,即 Sn = ( Sf + S size) mod 2 m,则发送方进入阻塞状态。
2.如果一个无差错且ackNo与某一个待确认分组相关的ACK到达,发送方滑动窗口(置 Sf = ackNo),并且,如果所有待确认分组都被确认了(ackNo = Sn)则计时器停止计时。若还有待确认分组未被确认,则重启计时器。
3.如果一个损坏的ACK或者虽无差错但ackNo与待确认分组无关的ACK到达,丢弃这个ACK。
4.如果计时器超时,发送方重传所有待确认分组并重启计时器。
q q阻塞状态  在这种情况下可能会发生三个事件:
1.如果一个无差错且ackNo与某一个待确认分组的ACK到达,发送方滑动窗口(置 Sf = ackNo),同时,若所有待确认分组都被确认了(ackNo = Sn)则计时器停止。若还有待确认分组未被确认,则重启计时器。然后发送方进入准备好状态。
2.如果一个损坏的ACK到达或者虽无差错但ackNo与待确认分组无关的ACK到达,丢弃这个ACK。
3.如果计时器超时,发送方重传所有待确认分组并重启计时器。
接收方 接收方总是在准备好状态。变量 Rn的初始值为0。可能会发生三个事件:
1.如果一个无差错且seqNo = Rn的分组到达,则这个分组中的报文被交付给应用层。然后窗口滑动到 Rn =( Rn + 1)mod 2 m。最后发送一个ackNo = Rn的ACK。
2.如果一个无差错但seqNo落在窗口之外的分组到达,则这个分组被丢弃,但是要发送一个ackNo = Rn的ACK。
3.如果一个损坏的分组到达,这个分组被丢弃。
发送窗口大小
我们现在可以来说明为什么发送窗口大小必须小于2 m。作为一个例子,我们选择,也就是说窗口大小可以是,或者说3。图13.27对一个大小为3的窗口和一个大小为4的窗口进行了比较。
图13.27 返回N协议的发送窗口大小
如果窗口大小是3(小于2 m)且所有三个确认都丢失了,那么唯一的那个计时器超时后所有三个分组被重传。此时接收方期盼的是分组3而不是分组0,因此这些重复的分组到达后会被正确地丢弃掉。另一方面,如果窗口大小是4(等于2 m)且所有确认都丢失了,发送方会发送重复的分组0。但是此时接收方的窗口正在期盼着接收分组0(下一个循环),所以它就接受分组0,它认为这不是一个重复分组,而是下一循环的第一个分组。这就是一个错误。从中我们可以看出发送窗口大小必须小于2 m
在返回 N协议中,发送窗口大小必须小于2 m,接收窗口大小始终为1。
13.7
图13.28所示为返回 N协议的一个例子。这是前向信道可靠,但反向信道不可靠的一个例子。没有数据分组丢失,但有些ACK延迟了,且其中一个ACK丢失了。这个例子还说明了如果确认被延迟或丢失,累计确认应当如何提供帮助。
图13.28 例13.7的流程图
在初始化之后有几个发送方事件。请求事件是由来自应用层的报文块触发的,到达事件是由来自网络层的ACK触发的,此处没有超时事件,因为在计时器超时之前所有待确认的分组都得到了确认。请注意,虽然ACK2丢失,但ACK3是一个累计确认,它既作为ACK3,也作为ACK2。在接收方一共发生了四个事件。
13.8
图13.29所示为在一个分组丢失后发生的情况。分组0、1、2和3被发送。但是分组1丢失了。接收方收到分组2和3,但它们因失序到达而被丢弃(期盼的是分组1)。当接收方收到分组2和3时,它会发送ACK1来表示自己期盼分组1。但是这些ACK对于发送方没有起到什么作用,因为这个ackNo等于 Sf,而不是大于 Sf,因此发送方丢弃它们。当超时事件发生后,发送方重传分组1、2和3,然后它们被确认。
返回N与停止等待的比较
读者可能发现在返回 N协议与停止等待协议之间有相似之处。停止等待协议实际上就是一种返回 N协议,不过它只有两个序号且发送窗口大小为1。换言之就是且。在返回 N协议中,我们说计算都是模2 m的,在停止等待协议中计算都是模2的,当时模2和模2 m是一样的。
图13.29 例13.8的流程图
13.2.4 选择重传协议
返回 N协议简化了接收方的处理过程。接收方只需跟踪一个变量,并且不需要对失序到达的分组进行缓存,它们被简单地丢弃掉。但是如果底下的网络层协议丢失了很多分组,那么这个协议的效率就会很低。每当一个分组丢失或损坏,发送方就要重传所有待确认的分组,虽然其中有些分组实际上已安全完好地被接收了。如果因为网络的拥塞致使网络层丢失了很多分组,那么对所有这些待确认分组的重传会令拥塞状况加剧,并最终导致更多的分组丢失。它具有一种雪崩效应并有可能导致网络完全崩溃。
人们设计的另一种协议称为 选择重传 Selective-Repeat SR 协议 ,就像名字所暗示的那样,它只重传选择的分组,也就是真正丢失的分组。这个协议的概要图如图 13.30 所示。
窗口
选择重传协议也使用了两个窗口:一个发送窗口和一个接收窗口。但是这个协议中的两个窗口与返回 N协议中的两个窗口有所不同。首先,它的发送窗口的最大值要小得多,是2 m −1,原因我们稍后再讨论。其次,它的接收窗口与发送窗口一样大。
图13.30 选择重传协议
发送窗口的最大值可以是2 m −1。例如,如果 m = 4,那么序号就是从0到15,但窗口的最大值只能是8(在返回 N协议中,这个值是15)。我们在图13.31中描绘了选择重传协议的发送窗口以强调它的大小。
图13.31 选择重传协议的发送窗口
选择重传的接收窗口与返回 N 协议的接收窗口完全不同。它的接收窗口与发送窗口一样大(最大为 2m 1 )。选择重传协议允许与接收窗口大小一样多的分组失序到达并且保存这些分组直到连续的一组分组被交付给应用层。因为发送窗口大小与接收窗口的相同,所以发送出来的所有分组都可以失序到达,而且会被保存直到交付为止。但是我们需要强调一点,在一个可靠的协议中,接收方是永远不会把分组失序地交付给应用层的。图 13.32 描绘了选择重传协议中的接收窗口。窗口中有阴影的小格子定义的是已经失序到达的分组,它们在被交付给应用层之前,先要等待那些更早发送出来的分组的到达。
计时器
理论上,选择重传要为每个待确认的分组使用一个计时器。当某个计时器超时后,只有相应的分组被重传。换言之,GBN将所有待确认的分组当作一个整体对待,而SR则分别对待每一个分组。但是,大多数应用了SR的运输层协议仅使用了一个计时器。因此我们也只使用一个计时器。
图13.32 选择重传协议的接收窗口
确认
这两个协议之间还存在其他一些区别。在GBN中,ackNo是累计的,它定义了下一个希望接收的分组的序号,同时也证实了在此之前的所有分组都已经安全完好地被接收了。在SR中,确认的语义与此不同。在SR中,ackNo只定义了安全完好地收到的那一个分组的序号,并不反馈任何其他分组的信息。
在选择重传协议中,确认号定义了无差错地接收到的那一个分组的序号。
13.9
假设发送方发送了6个分组:分组0、1、2、3、4和5。发送方接收到一个ackNo为3的ACK。如果这个系统使用的是GBN或者是SR,它的含义各是什么?
如果系统使用的是GBN,它就表示分组0、1和2都已被接收且无损坏,接收方现在期盼的是分组3。如果系统使用的是SR,它就表示分组3已经被接收且无损坏,这个分组没有说有关其他分组的任何事。
FSM
图13.33描绘了选择重传协议的FSM。它与GBN的类似,但有几处不同的地方。
发送方 发送方开始时处于准备好状态,但是之后它有可能进入两个状态之一:准备好状态和阻塞状态。下面列出了每种状态的事件及相应的动作。
q q准备好状态 在这种情况下可能会发生四个事件。
1.若一个来自应用的请求到达,发送方就产生一个序号置为 Sn的分组。这个分组的一个副本被保存起来,并且这个分组被发送出去。若计时器未运行则发送方启动计时器。 Sn的值递增, Sn = ( Sn + 1) mod 2 m。若窗口满,即 Sn = ( Sf + S size) mod 2 m,发送方就进入到阻塞状态。
2.若一个无差错且ackNo与某个待确认分组相关的ACK到达,该分组被标记为已确认。若ackNo = Sf,窗口向右滑动,直到 Sf指向第一个未被确认的分组(所有连续被确认的分组现在都滑出窗口外边了)。若还有待确认分组未被确认,则重启计时器,否则计时器停止计时。
3.若一个损坏的ACK到达或者虽无差错但ackNo与待确认分组无关的ACK到达,丢弃这个ACK。
图13.33 SR协议的FSM
4.若计时器超时,发送方重传窗口中所有未被确认的分组并重启计时器。
q q阻塞状态  在这种情况下可能会发生三个事件:
1.若一个无差错且ackNo与某一个待确认分组相关的ACK到达,该分组被标记为已确认。另外,若ackNo = Sf 则窗口向右滑动直到 Sf指向第一个未被确认的分组(所有连续被确认的分组现在都滑出窗口外边了)。若窗口滑动了,发送方就进入准备好状态。
2.若一个损坏的ACK到达或者虽无差错但ackNo与待确认分组无关的ACK到达,丢弃这个ACK。
3.若计时器超时,发送方重传窗口中所有未被确认的分组并重启计时器。
接收方 接收方总是在准备好状态。可能会发生三个事件:
1.若一个无差错且seqNo落在窗口中的分组到达,则这个分组被保存,且发送一个ackNo = seqNo的分组。另外,若seqNo = Rn,则这个分组以及所有前面到达的连续的分组都被交付给应用层,且窗口滑动,使 Rn 指向第一个空格。
2.若一个无差错但seqNo落在窗口之外的分组到达,则这个分组被丢弃,但是要返回一个ackNo = Rn的ACK给发送方。这样做的目的是,如果与某个seqNo < Rn的分组相关的ACK丢失了,发送方要能够滑动自己的窗口。
3.如果一个损坏的分组到达,这个分组被丢弃。
13.10
这个例子类似于例3.8(图13.29),其中分组1丢失了。我们描绘了在这种情况下选择重传协议是如何动作的。图13.34描绘了此情况。
在发送方,分组0被发送且被确认。分组1丢失了。分组2和3失序到达并被确认。当计时器超时,分组1(唯一未被确认的分组)重传并被确认。发送窗口滑动。
图13.34 例13.10的流程图
在接收方,我们需要区别对待分组的接受和向应用层的交付。在第二个到达时刻,分组2到达并且被保存和标记(阴影格),但是它不能被交付,因为分组1还没有到。在下一个到达时刻,分组3到达并被保存和标记,但是仍然没有分组能被交付。只有在最后一个到达时刻,也就是当分组1的副本姗姗来迟后,分组1、2和3才能一起被交付给应用层。向应用层交付分组需要两个条件:首先,已经到达的必须是一组连续的分组。其次,这一组连续的分组以窗口的前端为起始。在第一个到达时刻,只有一个分组且它就在窗口的前端。在最后一个到达时刻,一共有三个分组且第一个分组在窗口的前端。关键就是可靠的运输层允诺按顺序交付分组。
窗口大小
现在我们可以来说明为什么发送方和接收方的窗口的最大值只能是2 m的一半了。例如,我们选择 m = 2,也就是说窗口大小是2 m/2或者2。图13.35对大小为2的窗口和大小为3的窗口进行比较。
图13.35 选择重传,窗口大小
如果窗口大小是2且所有确认都丢失了,当分组0的计时器超时后分组0被重传。此时接收方期盼的是分组2而不是分组0,因此这个重复的分组会被正确地丢弃掉(序号0 不在窗口中)。如果窗口大小是 3 且所有确认都丢失了,发送方发送重复的分组 0 。但是这一次,接收方的窗口正在期盼着接收分组 0 0 属于窗口中),所以它就接受分组 0 ,它不认为这是一个重复的分组,而是认为这个分组是下一个循环的第一个分组。显然这是错误的。
 
在选择重传协议中,发送窗口和接收窗口的最大值只能是2 m的一半。
13.2.5 双向协议:捎带
在这一节我们讨论的四种协议全部都是单向的:数据分组仅在一个方向流动,而确认从另一个方向传过来。但是在现实生活中数据分组通常都是双向流动的:从客户到服务器,并且从服务器到客户。这就意味着确认也需要双向流动。一种称为捎带(piggybacking)的技术可用于提高双向协议的效率。当分组从A向B携带数据的同时也能够携带返回的确认,这些确认说明了从B发来的分组的到达情况。而当分组从B向A携带数据的同时也能够携带返回的确认,这些确认又说明了从A发来的分组的到达情况。
图13.36所示为利用捎带实现双向GBN协议的概要图。客户和服务器各使用两个独立的窗口:发送窗口和接收窗口。我们将这种情况(以及其他情况)的FSM留作练习。
图13.36 返回N协议中的捎带设计
要更细致地了解本章所讨论的内容,我们推荐以下书籍:[Com 06]、[Pet & Dev 03]、[Kur & Ros 08]、[Gar & Vid 04]、[Far 04]、[Tan 03]和[Sta 04] ,用方括号括起来的书目可以在本书末尾的参考书目清单中找到。另外,我们还要推荐一个提供了大量信息的论文:“The Transport Layer: Tutorial and Survey” ACM Computing Surveysvol. 31, no. 4, Dec. 1999,作者:Sami Iren,Paul D. Amer和Phillip T. Conrad。
确认号
开环拥塞控制
带宽时延积
捎带
客户−服务器范式
流水线方式
闭环拥塞控制
端口号
拥塞
进程到进程的通信
拥塞控制
选择重传协议
分用
序号
临时端口号
滑动窗口
有限状态机
套接字地址
返回 N协议
停止等待协议
负载
熟知端口号
复用
 
q q运输层协议的主要任务是提供进程到进程的通信。要定义进程,我们就需要端口号。客户进程用一个临时端口号来定义自己。服务器用一个熟知端口号来定义自己。
q q为了把报文从一个进程发送到另一个进程,运输层协议要对报文进行封装和解封。封装发生在发送端,解封发生在接收端。
q q源点的运输层执行报文的复用,就是从多个进程那里收集报文并传输。终点的运输层执行分用,就是把报文交付给不同的进程。
q q流量控制用于平衡生产者和消耗者之间数据的交换。在运输层,当消耗者尚未准备好接收分组时,我们就用缓存来保存这些分组。运输层的可靠性通过加入差错控制来实现,包括检测损坏的分组,重传丢失的以及损坏的分组,丢弃重复的分组,并为失序到达的分组重新排序。要管理流量控制和差错控制,我们使用了序号来为分组编号,并使用确认号指向编号的分组。
q q 运输层能够提供两种类型的拥塞控制:开环的和闭环的。在开环拥塞控制中,协议试图避免拥塞的发生。在闭环拥塞控制中,协议试图在拥塞发生之后检测并解除拥塞。
q q运输层协议能够提供两种类型的服务:无连接的和面向连接的。在无连接的服务中,发送方不用建立任何连接就可以向接收方发送分组。在面向连接的服务中,客户和服务器首先要在它们之间建立一条连接。只有在连接建立后才能交换数据。而当数据交换完毕后,连接需要被拆除。
q q本章我们讨论了几种通用的运输层协议。简单无连接协议既不提供流量控制,也不提供差错控制。面向连接的停止等待协议提供了流量控制和差错控制,但是效率很低。返回 N协议是停止等待协议的效率较高的一个版本,它利用了流水线方式。选择重传协议是对返回 N协议的改进,它在处理分组丢失上更具优势。所有这些协议都能通过捎带技术实现双向传输。
13.6.1 习题
1.发送方使用5位的序号向同一个终点发送了一个分组序列。如果序号从0开始,那么第100个分组的序号是什么?
2. 使用 5 位的序号,对以下几种协议来说,发送窗口和接收窗口的最大值分别是多少?
a.停止等待。
b.返回 N
c.选择重传。
3.为一个想象的机器画出FSM,它有三个状态:状态A(开始状态)、状态B和状态C,并有四个事件:事件1、2、3和4。以下是该机器的具体行为:
a.当在状态A时,可能发生两个事件:事件1和事件2。如果事件1发生,机器执行动作1并进入状态B。如果事件2发生,机器进入状态C(无动作)。
b.当在状态B时,可能发生两个事件:事件3和事件4。如果事件3发生,机器执行动作2,但仍然保持在状态B。如果事件4发生,机器就进入状态C。
c.当在状态C时,机器永远保持在这个状态。
4.请重新设计图13.15所示的FSM,假设连接的建立只需要交换3个分组就可以完成(合并分组2和3)。
5.重画图13.18,假设图中一共交换了5个分组(0、1、2、3、4),分组2丢失,且分组3在分组4之后到达。
6.创建一个类似图13.21所示的场景,其中发送方发送了三个分组。第一个和第二个分组到达且被确认。第三个分组因延迟而被重传。接收方在对原始的第三个分组的确认发出之后又收到了这个重复的分组。
7.创建一个类似图13.21所示的场景,其中发送方发送了两个分组。第一个分组到达并被确认,但是这个确认丢失了。发送方在计时器超时后重传该分组。第二个分组丢失并被重传。
8.重画图13.28,假设发送方发送了5个分组(0、1、2、3、4),分组0,1和2发送后被一个ACK一起确认,这个ACK在发送方发送完所有分组后到达。分组3被接收并通过一个ACK中确认。分组4丢失且重传。
9.重画图13.34,假设发送方发送了5个分组(0、1、2、3、4)。分组0,1和2按顺序逐个地接收并被确认。分组3延迟并在分组4之后被接收。
10.请回答以下与停止等待协议的FSM相关的问题(图13.20):
a.发送方状态机在准备好状态且 S = 0。下一个要发送的分组的序号是什么?
b.发送方状态机在阻塞状态且 S = 1。如果计时器超时,下一个要发送的分组的序号是什么?
c.接收方状态机在准备好状态且 R = 1。一个序号为1的分组到达。对这个事件的响应是什么?
d.接收方状态机在准备好状态且 R = 1。一个序号为0的分组到达。对这个事件的响应是什么?
11.请回答以下与返回 N协议( m = 6)的FSM相关的问题(图13.26):
a.发送方状态机在准备好状态, Sf = 0且 Sn = 15。下一个要发送的分组的序号是什么?
b.发送方状态机在准备好状态, Sf = 0且 Sn = 15。发生一个超时事件。有多少个分组要重发?它们的序号是什么?
c.发送方状态机在准备好状态, Sf = 0且 Sn = 15。一个ackNo = 13的ACK到达。 SfSn 的下一个值分别是什么?
d.发送方状态机在阻塞状态, Sf = 14且 Sn = 21。这个窗口是多大?
e.发送方状态机在阻塞状态, Sf = 14且 Sn = 21。一个ackNo = 18的ACK到达, SfSn 的下一个值分别是什么?发送方状态机的状态是什么?
f.接收方状态机在准备好状态且 Rn = 16。一个序号为16的分组到达。 Rn的下一个值是什么?对这个事件的响应是什么?
12.请回答以下与选择重传协议( m = 7位)的FSM相关的问题(图13.33):
a.发送方状态机在准备好状态, Sf = 0且 Sn = 15。下一个要发送的分组的序号是什么?
b.发送方状态机在准备好状态, Sf = 0且 Sn = 15。分组10的计时器超时。有多少个分组要重发?它们的序号是什么?
c.发送方状态机在准备好状态, Sf = 0且 Sn = 15。一个ackNo = 13的ACK到达。 SfSn 的下一个值分别是什么?对这个事件的响应是什么?
d.发送方状态机在阻塞状态, Sf = 14且 Sn = 21。这个窗口大小是多少?
e.发送方状态机在阻塞状态, Sf = 14且 Sn = 21。一个ackNo = 14的ACK到达,分组15和16已经确认。 SfSn 的下一个值分别是什么?发送方状态机的状态是什么?
f.接收方状态机在准备好状态且 Rn = 16。这个窗口大小为8。一个序号为16的分组到达。 Rn的下一个值是什么?对这个事件的响应是什么?
g.接收方状态机在准备好状态且 Rn = 16。这个窗口大小为8。一个序号为18的分组到达。 Rn的下一个值是什么?对这个事件的响应是什么?
13.6.2 研究活动
13.重画图13.16中所示的简单协议双向图(使用捎带技术)。
14.重画图13.19中所示的停止等待协议双向图(使用捎带技术)。
15.重画图13.30中所示的选择重传协议双向图(使用捎带技术)。
16.画出使用了捎带技术的简单协议的双向FSM图。请注意双方都需要发送和接收。
17. 画出使用了捎带技术的停止等待协议的双向 FSM 图。请注意双方都需要发送和接收。
18. 画出使用了捎带技术的返回 N 协议的双向 FSM 图。请注意双方都需要发送和接收。
19. 画出使用了捎带技术的选择重传协议的双向 FSM 图。请注意双方都需要发送和接收。
20.试用伪码(或者用某种计算机语言)写出与简单协议相关的FSM(图13.17)的两个算法。
21.试用伪码(或者用某种计算机语言)写出与停止等待协议相关的FSM(图13.20)的两个算法。
22.试用伪码(或者用某种计算机语言)写出与返回 N协议相关的FSM(图13.26)的两个算法。
23.试用伪码(或者用某种计算机语言)写出与选择重传协议相关的FSM(图13.33)的两个算法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值