计算机网络-运输层
运输层协议为运行在不同主机上的应用进程之间提供了逻辑通信(logic communication)。应用进程使用运输层提供的逻辑通信功能彼此发送报文,而无需考虑承载这些报文的物理基础的细节。
运输层协议是在端系统中而不是在路由器中实现的。运输层会将应用层的报文划分为较小的块,并为每块加上一个运输层首部以生成运输层报文段(segment)。
运输层与网络层的关系
运输层之下是网络层,网络层提供了主机之间的逻辑通信,而运输层是为运行在不同主机上的进程之间提供逻辑通信。
运输层协议将来自应用进程的报文移动到网络层,但对有关这些报文在网络核心如何一共并不做任何规定。中间路由器既不处理也不识别运输层加在应用层报文的任何信息。
运输协议能够提供的服务常常受限于低层网络层协议的服务模型。然而,即使低层网络协议不提供某些服务,运输层协议也能提供某些服务。如底层网络层协议是不可靠的,可能会使分组丢失、篡改和冗余,运输层协议也能为应用程序提供可靠的数据传输服务。
因特网运输层概述
UDP(用户数据报协议),为调用它的应用程序提供了一种不可靠、无连接的服务。
TCP(传输控制协议),为调用它的程序提供了一种可靠的、连接服务。
网络层协议有一个名字叫IP协议,即网际协议。IP为主机之间提供了逻辑通信。IP的服务模型是尽力而交付服务,但它不能确保报文段的交付,不保证报文段的按序交付,不保证报文段中的数据完整性。
UDP和TCP最基本的责任是,将两个端系统间IP的交付服务扩展为运行在端系统上的两个进程之间的交付服务。将主机间的交付扩展到进程间的交付被称为运输层的多路复用(transport-layer multiplexing)与多路分解(demultiplexing)。
多路复用与多路分解
一个进程有一个或多个套接字,由于在任一时刻,在接收主机上可能不止一个套接字,所以每个套接字上都有一个唯一标识符
每个运输层报文段中具有几个字段。在接收端,运输层检查这些字段,表示出接收套接字,进而将报文段定向到该套接字。将运输层报文段中的数据交付到正确的套接字的工作称为多路分解。
在源主机从不同套接字中收集数据块,并为每个数据块封装首部信息(这将在以后用于分解)从而生成报文段,然后将报文段传递到网络层,这些工作称为多路复用。
多路复用的要求:
- 套接字有唯一标识符
- 每个报文段有特殊字段来指示该报文段所要交付到的套接字
这些特殊字段是源端口号字段和目的端口号字段
运输层实现分解服务:在主机上的每个套接字都能够分配一个端口号,当报文段到达主机时,运输层检查报文段中的目的端口号,并将其定向到相应的套接字。
无连接(UDP)的多路复用与多路分解
如果应用开发者所编写的代码实现的是一个“周知协议”的服务端,那么开发者就必须为其分配一个相应的周知端口号。
通常,应用程序的客户端让运输层自动地分配端口号,而服务器端则分配一个特定的端口号。
一个UDP套接字是由一个二元组来全面标识的,该二元组包含一个目的IP地址和一个目的端口号。因此,如果两个UDP报文段有不同的源IP地址/源端口号,但具有相同的目的IP地址和目的端口号,那么这两个报文段将通过相同的目的套接字被定向到相同的目的进程。
报文段中的源端口号用于服务器为客户端发送响应报文。
面向连接(TCP)的多路复用和多路分解
TCP套接字是由一个四元组(源IP地址,源端口号,目的IP地址,目的端口号)来标识的。
当一个TCP报文段到达主机时,两个具有不同源IP地址或源端口号的报文段将被定向到两个不同的套接字,除非TCP报文段携带了初始创建连接的请求。
无连接运输:UDP
UDP只是做了运输协议能够做的最少工作。处理复用/分解功能及少量的差错检测外,它几乎没有对IP增加别的东西。
UDP报文段结构
UDP首部只有4个字段,每个字段由两个字节组成。
- 长度字段指明了包括首部在内的UDP报文长度(以字节为单位)
- UDP检验和提供了差错检测的功能,检验和用于确定UDP报文段从源到达目的地移动时,其中的比特是否发生了该改变。将传输报文中所有内容,每16比特的和进行反码运算,求和时遇到的任何溢出都被回卷(如果有进位,舍弃最高位),得到的结果会被放在校验和中。接收方会将所有内容(包括校验和)进行求和,如果结果是16个1,则表示没有问题,否则表示出现差错。
UDP虽然提供差错检测,但它不能差错恢复。一旦出现差错,UDP会将报文段丢弃,或者提交报文段和出错警告给应用层。
可靠数据传输原理
我们将较低层直接视为不可靠的点对点信道,只有在运输层使用可靠数据传输协议实现可靠信道的搭建。
构造可靠数据传输协议
经完全可靠信道的可靠数据传输
如果底层信道是完全可靠的,协议本身是简单的。
经具有比特差错信道的可靠数据传输
假设底层信道的模型是分组中的比特可能受损,但我们继续假定所有发送的分组是按其发送的顺序接收的。
我们让接收方在接收到报文段后,使用肯定确认(positive acknowledge)与否定确认(negative acknowledge)来表示接收状态。如果发送方接收到了接收方发送的否定确认,发送方会基于重传机制,重新发送该报文段。
这种传输协议被称为自动重传请求(AutomaticRepeat reQuest,ARQ)协议
ARQ需要三种功能处理差错:
- 差错检测:类似UDP的检验和,这些校验位将被汇集在协议报文段的分组检验和字段中。
- 接收方反馈:需要定义接收方用来表达接收状态的方式:“肯定确认”(ACK)和“否定确认”(NAK)。理论上,这些只需要一个比特为:如用0表示NAK,1表示ACK
- 重传:当接收方收到有差错的分组时,发送方将重传该报文段。
发送方在传输报文段后,会进入等待状态,等待接收方的ACK或NAK,此时发送方将不会发送一块新数据,由于这种行为,这样类似ARQ的协议被称为停等协议。
这类协议的缺陷在于,我们无法保障ACK/NAK的报文能够可靠传输。
我们可以通过根据接收方发来的确认报文段是否能够通过差错检验,如果不能通过,直接重传报文段的方式解决。但这会带来报文冗余(接收方接收了多次相同的报文)的新问题。这个冗余问题可以通过给报文段添加一个新字段,用来给报文分组编号的方式解决。
经具有比特差错的丢包信道的可靠数据传输
除了假定报文段会比特受损外,底层信道还有可能丢包。
我们让发送方负责检测和恢复丢包工作。发送方如果收不到接收方的响应(无论是因为发送方的传输报文段丢包还是接收方的ACK丢包),如果发送方愿意等待足够长的时间以确定分组已丢失,则它只需要重传该数据即可。
发送方会在经历一个特别大的时延后重发报文段,无论中间是否发生丢包。为了实现基于时间的重传机制,需要一个倒计数定时器(countdown timer),在一个给定的时间量过期后,可中断发送方。
过早超时:虽然没有发生丢包,但是因为有较大的时延,发送方仍进行了重传。
流水线可靠数据传输协议
之前构造的经具有比特差错的丢包信道的可靠数据传输协议是一个功能正确的协议,但由于他是一个停等协议,所以他的性能不尽如人意。
为了解决这个性能问题的一个简单方法是:不使用停等协议,允许发送方发送多个分组而无需等待确认。这种技术被称为流水线(pipelining)。
回退N步
在回退N步(GBN,也称为滑动窗口协议)协议中,允许发送方发送多个分组不需要等待确认,但它受限于在流水线中为确定的分组不能超过某个最大允许数N。N也被称为窗口长度。
如果将基序号(base)定义为最早的未确认的报文段需要,将下一个序号(next seqnum)定义为最小的未使用序号,我们将序号范围分割成4段:
- [0,base-1]段内的序号对应于已经发送并被确认的分组
- [base,nextseqnum-1]段内对应已经发送但未被确认的分组
- [nextseqnum,base+N-1]段内的序号能用于那些要被立即发送的分组,如果有数据来自上层的话
- [base+N,+∞)直到当前流水线中未被确认的分组(特别是序号为base的分组)被确认前不能被使用的序号
在DBN中,接收方如果接收到了一个序号为n的报文段,且这个报文段是按序的(序号n前的报文段都已经确认接收了)则接收方为报文段n发送一个ACK,并将该分组中的数据部分交付到上层。因为接收方需要按序接收,所以当接收方接收到的报文段不是按序的,则接收方会将后续接收到的报文全部丢掉,直至接收到按序的报文段。因此,使用累积确认是GBN一个自然的选择。
假设接收方期望收到分组n,但分组n+1却到了,接收方会将分组n+1丢弃,并发送n-1(上一个已经到达的分组)的ACK要求发送方重传。
假设窗口长度为4:
选择重传
单个分组的差错就能引起GBN重传大量分组,许多分组根本没有必要重传,导致了性能问题。选择重传(SR)协议通过让发送方仅重传那些它怀疑在接收方出错(丢失或比特差错)的分组而避免了不必要的重传。
假设窗口长度为4:
由于发送方和接收方窗口在实际发送过程中不同步,可能会引起下面的问题:
假设窗口长度为3:
接收方无法判断0号分组是重传的分组还是新到的0号分组。
所以对于SR协议而言,窗口长度必须小于等于序号空间(序号的最大值)的一半。例子中的序号空间为4,窗口长度就不能超过2。
TCP协议
TCP被称为是面向连接的,因为在一个应用程序可以开始向另一个应用程序发送数据之前,这两个进程必须先互相“握手”,即它们相互发送些预备报文段,连接的双方都将初始化与TCP连接相关的许多TCP状态变量。
TCP连接提供的是全双工服务,也总是点对点的。所谓的“多播”即在一次发送的操作中,从一个发送方将数据传送给多个接收方,对TCP来说这是不可能的。
TCP可从缓存中取出并放入报文段中的数据数量受限于最大报文段长度(Maximum Segment Size MSS),MSS通常根据最初确定的由本地发送主机发送的最大链路层帧长度(最大传输单元(Maximum TransmissionUnit,MTU))来设置。以太网和PPP链路层协议都具有1500字节的MTU,MSS的典型值为1460字节。(TCP报文段加上TCP/IP首部长度(通常为40字节))。MSS是最大有效载荷的大小(不包含TCP的报文段首部)。
TCP报文段结构
MSS限制了报文段数据字段的最大长度,当TCP发送一个大文件,TCP通常是将该文件划分成长度为MSS的若干块。
- 4比特的首部字段指示了TCP报文首部的长度(因为选项字段的长度是可变的,所以需要首部长度随之改变)
- 6比特的标志字段:ACK比特用于确认字段中的值是否有效。RST、SYN和FIN用于建立连接和拆除连接。当PSH比特设置为1时,指示接收方应立即将数据交给上层。URG比特用来指示报文里是否由被发送端上层设置为“紧急”的数据(由紧急数据指针指出)。
- 32比特的序号是该报文段首字节的字节流编号(假设数据流由一个包含500000字节的文件组成,MSS为1000字节,数据流的首字节编号为0,TCP将数据流拆分成500个报文段。给第一个报文段分配序号0,第二个报文段分配序号1000,以此类推每个序号被填入相应的TCP报文段首部的序号字节中)
- 32比特的确认号:主机A填充进报文段的确认号是主机A期望从主机B收到的下一字节的序号。用于确认收到确认号之前所有的字节。因此TCP也被称为累计确认。
重传时间
TCP采用超时/重传机制来处理报文段的丢失问题。
TCP会在某一个时刻做一个SampleRTT测量(样本报文的来回循环时间),仅为一个没有被重传过的,已发送的,没有被接收的报文段进行测量。同时TCp维持一个SampleRTT均值(称为EstimatedRTT,ERTT)。ERTT的计算公式是:ERTT =(1- 0.125)ERTT + 0.125SampleRTT。(从统计学观点讲,这种平均称为指数加权移动平均,SampleRTT经过几次计算后权值急速下降,ERTT受新SampleRTT的影响较大)
处理估算RTT之外,测量RTT的变化也是有价值的,DeVRTT用于估算SampleRTT一般会偏离ERTT的程度,它的计算公式是:DevRTT = (1-0.25)DevRTT +0.25*|SampleRTT - ERTT|
TCP确定重传超时时间间隔,考虑了大部分因素,计算公式是:T = ERTT +4*DevRTT。当RTT的波动大时,DevRTT就大,也就是说给超时时间的余量就大。初始的超时时间间隔为1s
图片来源于网络