如何理解运输层?
现在考虑有两个家庭,H1和H2,两个家庭有12个孩子喜欢互相写信,H1家庭的孩子C1与H2家庭的孩子C2负责收集信件送到邮局,再从邮局拿信件分发给其他人。
在这里例子中,应用层报文 = 信封上的字符、进程 = 孩子们、主机 = 家庭、运输层协议 = C1 and C2、网络层协议 = 邮政服务。
运输层协议为运行在不同端系统上的应用进程之间提供了逻辑通信,并且运输层协议只工作在端系统中,在端系统中,运输层协议将来自应用进程的报文移动到网络边缘(网络层),反之亦然。
运输层协议有UDP(用户数据报协议)和TCP(传输控制协议),负责将两个端系统间IP的交付服务扩展为运行在端系统上的两个进程之间的交付服务。
进程到进程的数据交付和差错检查是两种最低限度的运输层服务,也是UDP所能提供的仅有的两种服务。TCP在此基础上还提供了可靠数据传输和拥塞控制。
多路复用&多路分解
多路复用与多路分解就是将由网络层提供的主机到主机交付服务延伸到为运行在主机上的应用程序提供进程到进程的交付服务。
当C1从邮递员处收到一批信件,并通过查看收信人名字而将信件亲手交给它的兄弟姐妹时,执行的就是多路分解操作;当C2从兄弟姐妹那里收集信件并交给邮递员时,执行的就是多路复用操作。
一个进程有一个或多个套接字,在接收主机中的运输层实际上并没有将数据直接交付给进程,而是将数据交给了一个中间的套接字。任意时刻,接受主机上可能有不止一个套接字,所以每个套接字都有一个唯一的标识符,标识符的格式取决于TCP还是UDP。
将运输层报文段中的数据交付到正确的套接字的工作称为多路分解,在源主机从不同的套接字中收集数据块,并为每个数据块封装上首部信息从而生成报文段,然后将报文段传递到网络层,所有这些工作称为多路复用。
UDP套接字是由一个二元组全面标识的,该二元组包含一个目的IP地址和一个目的端口号。TCP套接字是由一个四元组(源IP地址、源端口号、目的IP地址、目的端口号)来标识的。
UDP
UDP首部有4个字段(源端口号、目的端口号、长度、检验和),每个字段占2个字节,长度指的是整个UDP报文段(首部+数据)的字节数,接收方使用检验和来检查在该报文段中是否出现了差错。
虽然UDP提供差错检测,但它对差错恢复无能为力。UDP的某种实现只是丢弃受损的报文段,其他实现是将受损的报文段交给应用程序并给出警告。
可靠数据传输
自动重传请求(ARQ)协议,通过控制报文使得接收方可以让发送方知道哪些内容被正确接收,哪些内容接收有误并因此需要重复。
ARQ还需要差错检测(比特差错、检验和)、接收方反馈(肯定确认ACK、否定确认NAK)、重传三种协议来处理存在比特差错的情况。
停等协议:当发送方处于等待ACK或NAK的状态时,它不能从上层获得更多的数据,仅当接收到ACK并离开该状态时才能发生这样的事件。因此发送方将不会发送一块新数据,除非发送方确信接收方已正确接收当前分组。
一个比较严重的问题是,ACK或NAK分组受损的可能,解决该问题的一个简单方法,是在数据分组中添加一新字段,让发送方对其数据分组编号,即将发送数据分组的序号放在该字段,于是接收方只需检查序号即可确定收到的分组是否一次重传。
对于停等协议,发送方无法理解接收方的ACK/NAK时,就重传分组,接收方通过序号判断该分组是一个重传分组还是一个新分组。
但是除了解决比特受损的问题外,我们还要考虑底层信道的丢包问题,即怎样检测丢包以及发生丢包后该做些什么?
我们让发送方负责检测和恢复丢包工作,假设发送的分组丢失或者接收方ACK丢失,发送方收不到应当到来的接收方的响应,我们可以让发送方等待一个往返+分组处理的时延,但是这个时延在最坏情况下意味着发送方要等待很长时间。
因此需要设置一个超时时间,如果在这个时间内没有收到ACK,则重传该分组,即使接收方已经收到了这个分组。这也就意味着在发送方到接收方的信道中引入了冗余数据分组。对于冗余数据分组,我们依旧可以通过上文的序号机制来处理。
对于发送方来说,无论是一个数据分组丢失,还是一个ACK丢失,或者只是分组或ACK超时,都通过重传来解决,为了实现基于时间的重传机制,需要一个倒计数定时器:①每次发送一个分组(包括新分组和重传分组)时,启动一个定时器;②响应定时器中断;③终止定时器。
通过检验和、序号、定时器、肯定和否定确认分组这些技术,我们得到了一个可靠数据传输协议,我们称之为rdt3.0或比特交替协议。
流水线可靠数据传输协议
rdt3.0性能问题的核心在于其是一个停等协议,还有发送方和接收方的底层协议处理时间,以及可能出现在发送方与接收方之间的任何中间路由器的处理与排队时延。
解决办法是不以停等的方式运行,允许发送方发送多个分组而无须等待确认,因为许多从发送方向接收方输送的分组可以被看成是填充到一条流水线中,因此这种技术被称之为流水线。
- 必须增加序号范围,因为每个输送中的分组(不算重传)必须有一个唯一的序号,而且也许有多个在输送中的未确认报文。
- 协议的发送方和接收方两端也许不得不缓存多个分组,发送方最低限度应当能缓冲那些已发送但没有确认的分组,接收方或许也需要缓存那些已正确接受的分组。
- 所需序号范围和对缓冲的要求取决于数据传输协议如何处理丢失,损坏及延时过大的分组,解决流水线的差错恢复有两种基本方法:回退N步和选择重传。
回退N步(GBN)协议
GBN协议允许发送方发送多个分组,而不需等待确认,但也受限于在流水线中未确认的分组数不能超过某个最大允许数N。
假设GBN协议的序号范围为0-K,那么该序号范围可以被划分为4段(已发送并被确认的分组、已发送但未被确认的分组、即将被发送的分组、不可使用的序号)。
其中已发送但未被确认的分组与即将被发送的分组的长度为窗口长度N,随着协议的运行,该窗口在序号空间向前滑动,因此GBN协议也常被称为滑动窗口协议。
一个分组的序号承载在分组首部的一个固定长度的字段中,如果该字段长k位,则序号范围[0, 2^k-1],所有涉及序号的运算必须使用模2^k运算,因此序号空间可被看作是一个长度为2^k的环。
GBN的发送方必须响应三种类型的事件。
- 上层的调用。只有窗口未满才产生一个分组并发送,以及更新相应的变量。
- 收到一个ACK。对序号为n的分组采用累积确认的方式,表明接收方已正确接收到序号为n及n之前的所有分组。
- 超时事件。“回退n步”来源于出现丢失和时延过长分组时发送方的行为,如果超时,发送方重传所有已发送但还未被确认过的分组。
GBN的接收方如果一个序号为n的分组被正确接收到,并且按序,则接收方为分组n发送一个ACK,并将该分组中的数据部分交付到上层。在所有其他情况下,接收方丢弃该分组,并为上一个按序接收的分组重新发送ACK。看上去丢弃一个正确接收但失序的分组有些愚蠢,但是接收方不需要缓存一个失序分组,因为这个被丢弃的分组会因为重传规则再次被发送方发送。
选择重传
GBN协议允许发送多个分组,避免了停等协议中的信道利用率问题,但是在GBN协议中,单个分组的差错就能够引起大量分组的重传,许多分组根本没必要重传,随着差错率的增加,流水线可能会被这些不必要重传的分组充斥。
选择重传(SR)协议通过让发送方仅重传怀疑在接收方出错的分组,从而避免不必要的重传。SR接收方将确认一个正确接收的分组而不管其是否有序,失序的分组将被缓存直到之前所有丢失分组(序号更小的分组)都被收到为止,此时才可以将一批分组按序交付给上层。
SR发送方动作:
- 从上层接收到数据后,SR发送发检查下一个可用于该分组的序号。如果序号位于窗口内,则打包数据发送。否则就像GBN一样缓存数据或者返回给上层以便以后传输。
- 定时器再次被用来防止丢失分组,但现在对每个分组都要有其自己的逻辑定时器,因为超时发生后只发送单个分组。
- 如果收到ACK,且分组序号在窗口内,则标记该分组为已接收。如果序号位于窗口开始,那么窗口右移到具有最小序号的未确认分组处,如果窗口移动了且有序号落在窗口的未发送分组,则发送这些分组。
SR接收方动作:
- 序号在窗口内的分组被正确接收,此时收到的分组落在接收方的窗口内,一个选择ACK回给发送方。如果该分组之前没收到过,则缓存该分组。如果该分组序号位于窗口开始,则该分组以及以前缓存的序号连续的分组交付给上层,接着窗口向右移动。
- 上一个窗口内的分组被正确收到,需要产生一个ACK,即使该分组之前确认过。
- 其他情况忽略该分组。
对于序号空间的一个现实问题是,序号的范围是有限的,这对接收方的问题就在于无法确定一个分组是新的分组还是重传的分组,因此对于SR协议窗口长度必须小于或等于最大序号的一半,这样才不会在连续的两个窗口内出现拥有同一个序号的分组。
可靠机制总结
- 检验和:用于检测在一个传输分组中的比特错误。
- 定时器:用于超时重传,数据分组超时,或者ACK分组超时(接收方会有冗余副本)。
- 序号:为发送的分组按序编号,接收分组序号间的空隙使得接收方可以检测出丢失的分组,具有相同序号的分组可以使接收方检测出一个分组的冗余副本。
- 确认:接收方用于告诉发送方一个分组或一组分组已被正确的接收到了。确认报文通常携带着被确认的分组或多个分组的序号。确认可以逐个或累积,取决于协议的类型。
- 否定确认:接收方用于告诉发送方一个分组或一组分组未被正确的接收。否定确认报文通常携带着未被正确接收的分组的序号。
- 窗口、流水线:发送方也许被限制仅发送那些序号落在一个指定范围内的分组。窗口长度可以根据接收方接收和缓存报文的能力、网络中的拥塞程度或两者情况来设置。
TCP
TCP是因特网运输层面向连接的可靠地运输协议,为了提供可靠数据传输,依赖于上文讲述的可靠数据传输的原理,其中包括差错检测、重传、累积确认、定时器以及用于序号和确认号的首部字段。
TCP复杂且重要,为了避免文章过长,会另起一篇新文章具体讲述TCP。