计算机网络运输层两种服务,计算机网络(5)| 运输层

5.1 运输层协议概述

从通信和处理信息的角度看,运输层是向它上面的应用层提供通信服务的,它属于面向通信部分的最高层,同时也是用户功能中的最低层。当网络的边缘部分中的两台主机使用网络的核心部分的功能进行端到端的通信时,只有主机的协议栈才有运输层,而网络核心部分中的路由器在转发分组时都只用到下三层的功能。

5.1.1 运输层的两个主要协议

运输层的两个主要协议TCP/IP都是互联网的正式标准,即:

(1)用户数据报协议UDP

(2)传输控制协议TCP

运输层协议

UDP在传输数据之前不需要先建立连接。远地主机的运输层在收到UDP报文之后,不需要给出任何确认。尽管UDP不提供可靠交付,但是在某些情况下UDP却是一种有效的工作方式。

TCP则是面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。TCP不提供广播或者多播服务。由于TCP要提供可靠的面向连接的运输服务,因此需要增加很多的开销。

5.1.2 运输层的端口

TCP/IP的运输层用一个16位端口号来标志一个端口。端口号只有本地意义。它是为了标志本计算机应用层中的各个进程在和运输层交互时的层间接口。

运输层的端口号分为以下两类:

(1)服务器端使用的端口号:它主要分为系统端口号0~1023和登记端口号1024~49151。

常用的端口号

(2)客户端使用的端口号:49152~65535,这类端口号仅在客户端进程运行时才动态选择。当服务器收到客户端进程的报文时,就知道客户端进程的端口号。因而可以把数据发送给客户进程。

5.2 用户数据报协议UDP

5.2.1 UDP概述

用户数据报协议相比于IP的数据报服务就是只增加了复用、分用和差错检测功能。UDP的主要特点是:

(1)UDP是无连接的,发送数据之前不需要建立连接,因此减少开销和发送数据之前的时延。

(2)UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的连接状态表。

(3)UDP是面向报文的。发送方的UDP对应用交下来的报文,添加首部后就向下交付给IP层。不对报文做任何处理,因此当报文过长时,IP层可能需要进行分片处理。

(4)UDP没有拥塞控制,网络出现的拥塞不会使源主机的发送速率减低。

(5)UDP支持一对一、一对多、多对一和多对多的交互通信。

(6)UDP的首部开销小,只有8个字节。

5.2.2 UDP的首部格式

UDP有两个字段:数据字段和首部字段。先介绍首部字段,它是由4个字段组成的,每个字段只有2个字节,总共有8个字节。各个字段的意义如下:

(1)源端口:源端口号。在需要对方回信时选用。不需要时可用全0。

(2)目的端口:目的端口号。在这终点交付报文时必须使用。

(3)长度:UDP用户数据报的长度,其最小值是8(只有首部)。

(4)检验和:检测UDP用户数据报在传输中是否有错,有错则丢弃。

UDP

UDP用户数据报之前增加一个12字节的伪首部,它的作用主要是用来计算校验和的。当在计算校验和时,临时添加在UDP用户数据报前面,得到一个临时的用户数据报,检验和就是按照这个临时的UDP数据报来计算的。伪首部既不向上传送也不向下提交。

当在传送用户数据报时,如果接收方UDP发现收到的报文中目的端口号不正确(即不存在对应于该端口号的应用进程),就丢弃该报文,并由网际控制报文协议ICMP发送“端口不可达”差错报文给发送方。

5.3 传输控制协议TCP概述

5.3.1 TCP最主要的特点

TCP的主要特点如下:

(1)TCP是面向连接的运输层协议。应用程序在使用TCP协议之前,必须先建立TCP连接。传送数据完毕后,必须释放TCP连接。

(2)每一条TCP连接只能有两个端点。每一条TCP连接只能是点对点的。

(3)TCP提供可靠交付的服务。通过TCP连接传送的数据,无差错、不丢失、不重复,并且按序到达。

(4)TCP提供全双工通信。TCP允许通信双方的应用进程在任何时候都能发送数据。

(5)面向字节流。TCP中的流指的是流入到进程或进程流出的字节序列。虽然应用程序和TCP的交互是一次一个数据块,但TCP把应用程序交下来的数据看成一连串的无结构的字节流。TCP不保证发送方发送的数据块和接收方接收的数据块一致,但保证程序接收到的字节流和程序发送的字节流一致。

5.3.2 TCP的连接

TCP连接的端点叫做套接字或者插口。套接字是指将端口号拼接到IP地址之后,即:

套接字socket = (IP地址:端口号)

每一条TCP连接唯一的被通信两端的两个端点所确定。即:

TCP连接::= {socket1,socket2} = {(IP1:port1),(IP2:port2)}

5.4 可靠传输的工作原理

5.4.1 停止等待协议

1.无差错情况

如图所示,A发送分组M1,发送完毕就暂停发送,等待B的确认,B收到了M1就向A发死你确认。A在收到了对M1的确认之后,就再发送下一个分组M2,以此类推。

无差错情况

2. 出现差错

如图所示,当B接收M1时检测出了差错,就丢弃M1,其他什么也不做。而A只要超过了一段时间没有收到确认,就会认为刚才发送的分组丢失了,因而重传前面发送过的分组,这就叫做超时重传,而实现超时重传则需要A为每一个已发送的分组都设置一个超时计时器。

需要注意以下三点:

(1)A在发送完一个分组后,必须暂时保留已发送的分组的副本。

(2)分组和确认分组必须编号,这样才能明确哪一个发出的分组收到了确认。

(3)超时计时器设置的重传时间应当比数据在分组传输的平均往返时间更长。

超时重传

3. 确认丢失和确认迟到

如图所示,B所发送的对M1确认丢失了,A在设定的超时重传时间内没有收到确认,所以无法知道自己发送的分组是怎样出错的,所以会重传M1,而当B又收到了重传的分组M1,这时应该采取两个行动:

(1)丢弃这个重复分组M1。

(2)向A发送确认。

确认丢失

还有一种情况就是在传输过程中没有出现差错,但B对分组M1的确认迟到了,而A会收到重复的确认,A收下后就会丢弃,B仍然会收到重复的M1,并且同样要丢弃重复的M1,并且重传确认分组。

确认迟到

4. 信道利用率

停止等待协议的优点是简单,缺点则是信道的利用率太低。我们用TD表示A发送分组需要的时间,TA表示B发送确认分组需要的时间,RTT为往返时间,则:

信道的利用率:U=TD/(TD+RTT+TA)

为了提高传输的效率,发送方可以不使用低效率的停止等待协议,而是采用流水线传输的方式。即不必每发完一个分组就停下来等待对方的确认,这样就可以使信道上一直有数据在不间断的传送。

流水线传输

当使用流水线传输时,就要使用下面介绍的连续ARQ协议和滑动窗口协议。

5.4.2 连续ARQ协议

如图表示的是发送方维持的发送窗口,它指的是位于发送窗口内的5个分组都可以连续发送出去而不需要等待对方的确认。同时连续ARP协议规定,发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置。

连续ARQ协议工作原理

对于接收方采用的则是累计确认的方式,即接收方不必对收到的分组逐个发送确认。而是在收到几个分组后,对按序到达的最后一个分组发送确认,这就表示:到这个分组为止的所有分组都已正确收到了。这种方式的优点是:容易实现,即使确认丢失也不必重传(意思是发送方不必重传)。但缺点是不能向发送方反映出接收方已经正确收到的所有分组信息。

5.5 TCP报文段的首部格式

TCP虽然是面向字节流的,但传送TCP的数据单元却是报文段。一个TCP报文段可以分为首部和数据两部分。

TCP报文段的首部格式

首部固定部分各字段的意义如下:

(1)源端口和目的端口:各占2个字节,分别写入源端口号和目的端口号。

(2)序号:占4个字节,序号范围0~2^32-1,当需要达到最大值后,下一个序号又回到0。TCP是面向字节流的,因此这里的序号是指字节的序号,TCP连接中传送的每一个字节都按序编号,首部中的序号值应该是本报文段的第一个字节的序号。比如,一个报文段的序号值为301,而携带的数据共有100个字节。这表明本报文的数据的第一个字节的序号是301,最后一个字节的序号是400。下一个报文的序号应该是401。

(3)确认号:占4个字节,期望收到对方下一个报文段的第一个数据字节的序号。比如,B正确收到A的报文段,序号为501,数据长200。因此B希望收到A的下一个数据序号为701,则B在发送给A的确认报文段中把确认号设为701。

(4)数据偏移:占4位,指出数据起始处举例TCP报文段的起始处有多远,其实就是指出了TCP报文的首部长度。单位是4字节,4位的最大值是15,因此首部长度最大为4×15=60字节。

(5)保留:占6位,保留位今后使用,目前默认为0.

(6)紧急URG:当URG=1时,紧急指针有效。告诉系统该报文段有紧急数据,应尽快传送,而不是按照原来的排队顺序来传送。

(7)确认ACK:当ACK=1时确认号字段才有效。当ACK为0时确认号无效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置为1。

(8)推送PSH:PSH=1时,发送方立即创建报文发送出去,接收方也会尽快交付。

(9)复位RST:当RST=1,表明TCP连接中出现严重差错,必须释放连接,然后重新建立连接。

(10)同步SYN:在建立连接时用来同步序号。当SYN=1而ACK=0时,这是一个连接请求报文段。若对方同意连接,则应在响应的报文段使SYN=1和ACK=1。

(11)终止FIN:用来释放连接。当FIN=1时,表明报文段的发送方的数据已经发送完毕,要求释放运输连接。

(12)窗口:占2个字节,窗口值告诉对方:从本报文段首部的确认号算起,接收方目前允许对方发送的数据量。之所以有这个限制是因为接收方的数据缓存是有限的。

(13)检验和:占2个字节,检验和的计算和UDP一样,检验首部和数据两部分,而且依然要加上伪首部,伪首部的格式和UDP一致,但把第四个字段的17改为6。

(14)紧急指针:占2个字节。URG=1时才有效。指出本报文段的紧急数据的字节数。

(15)选项:长度可变,最长40个字节。

5.6 TCP可靠传输的实现

为了后面讲述的方便,我们假设数据传输只在一个方向进行,即A发送数据,B给出确认。

5.6.1 以字节为单位的窗口滑动

TCP的滑动窗口是以字节为单位的。如图所示,现在假定A收到了B发来的确认报文段,其中的窗口是20字节,而确认号是31,根据这2个数据,A就构造出自己的发送窗口。

A构造出的发送窗口

发送窗口表示:在没有收到B的确认的情况下,A可以连续把窗口内的数据都发送出去。凡是已经发送过的数据,在未收到确认之前都必须暂时保留,以便在超时重传时使用。发送窗口后面的部分表示已发送且已经收到了确认。而发送窗口前沿的部分表示不允许发送的。

现在假定A发送了序号为31~41的数据。这时发送窗口位置并未改变但是发送窗口内靠后面有11个字节表示已发送但是未收到确认。而发送窗口内靠前面的9个字节时允许发送但未发送的。如图所示:

A发送了11个字节数据

而对于B,它的接收窗口大小是20,在接收窗口外面到30号位置的数据是接收并确认的,因此可以丢弃。在下图中,B收到了32和33的数据,但它们不是按序到达的,因为并没有收到31号数据。B只能对按序达收到的数据中的最高序号给出确认,因此B发送的确认报文字段的确认号依然是31号。

B的接收

现在假定B收到了序号为31的数据,并把31~33的数据交付主机,然后B删除这些数据。接着把窗口向前移动3个序号,同时给a发送确认,其中的窗口值仍为20,但确认号变为34。表明B已经收到序号33为止的数据。

A收到了新的确认号

当A发送完窗口内的所有数据后,未收到任何确认时,窗口内就没有可发送的数据。经过一段时间后(超时计时器),若仍未收到确认,A将会重新发送。

已发送但是未确认

5.6.2 超时重传时间的选择

因为TCP的发送方在规定的时间内没有收到确认就要重传已经发送的报文段,但是重传时间的选择却TCP最复杂的问题之一。为此TCP采用了一种自适应算法,它记录了一个报文段发出的时间以及收到相应的确认的时间。这两个时间之差就是报文段的往返时间RTT,同时TCP保留了RTT的加权平均往返时间RTTs。而RTTD是RTT的偏差加权平均值,它与RTTs和新的RTT样本之差有关。

超时重传时间的算法如下:

第一次测量时,加权平均往返时间取往返时间RTT,以后每次测量到一个新的RTT,按以下公式计算:

新的RTTs = (1-a) X (旧的RTTs) +a X (新的RTT样本)

(其中0<=a<=1)

第一次测量时,RTT偏差的加权平均等于RTT的一半,以后的测里中,按以下公式计算:

新的RTTD = (1-b) X (旧的RTTD) + b X |RTTs-新的RTT样本|

(0<=b<1)

综上超时重传时间RTO计算如下:

RTO = RTTs + 4 X RTTD

5.6.3 选择确认SACK

若收到的报文无差错,只是未按序号,使用选择确认SACK可是让发送方发送那些未收到的数据,而不重复发送已经收到的那些数据。如果要使用选择确认SACK,那么在建立TCP连接时,就要在TCP首部的选项中加上“允许SACK”的选项,并且双方必须都事先商量好。

5.7 TCP的流量控制

5.7.1 利用滑动窗口实现流量控制

流量控制就是指让发送方的发送速率不要太快,要让接收方来得及接收。而利用滑动窗口机制就可以很方便的在TCP连接上实现对发送方的流量控制。

流量控制举例

如上图所示,接收方B进行了三次流量控制。第一次把窗口减小到rwnd=300,第二次又减到rwnd=100,最后是rwnd=0,即不允许发送方再发送数据了。

但是我们应该考虑一种情况,就是当接收方B的存储已满时,会向发送方发送零窗口的报文段,接着B的存储又有了一些空间,B再向A发送一个不为零的窗口值,但这个报文丢失了,结果就是双方一直等待下去。所以为了解决这个问题,TCP为每一个连接设有一个持续计时器。只要TCP连接的一方收到对方的零窗口通知,就启动持续计时器,当计时器到期后,就发送一个探测段文段,而对方就在确认这个探测段时给出了现在的窗口值。如果窗口仍然是0,那么收到这个报文段的一方就重新设置持续计时器,反之则死锁的僵局就可以打破了。

5.7.2 TCP的传输效率

应用程序把数据传送到TCP的发送缓存后,TCP在何时发送这些数据?,在TCP的实现中广泛使用了Nagle算法。具体算法如下:

(1)若发送应用进程要把数据逐个字节地送到TCP的发送缓存,则发送方就把第一个数据字节先发出去,把后面到达的数据字节都缓存起来。

(2)方发送方收到对第一个数据字节的确认后,再把发送缓存中的所有数据组装成一个报文发送出去,同时继续对后续到来的数据进行缓存。

(3)只有收到对前一个报文段的确认后才继续发送下一个报文段。

当数据到达快而网络速度慢时,这种方法可以明显减少网络带宽。Nagle还规定:当到达的数据达到窗口的一半或最大报文长度时就立即发送一个报文。

但还还需要考虑一个叫做糊涂综合征的问题,具体内容是若接收方的缓存已满,应用进程每次只从缓存中取1个字节,然后向发送方确认,并把窗口设为1个字节(缓存只空了1个字节的空间),接着发送方发来1个字节,接收方发回确认,仍然将窗口设为1,这样进行下去,网络的利用率很低。

为了解决这个问题,可以让接收方等待一段时间,使得或者缓存已有足够的空间或者等到接收缓存已有一半的空闲空间。此时,接收方就发出确认报文,并向发送方通知当前窗口的大小。

5.8 TCP的拥塞控制

5.8.1 拥塞控制的一般原理

拥塞是指在某一段时间内,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就会变坏的情况。而所谓的拥塞控制就是防止过多的数据注入到网络当中,这样可以使网络中的路由器或者链路不致过载,它是一个全局性的过程,涉及到所有的主机和路由器,而流量控制往往是指点对点通信量的控制。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。

5.8.2 TCP拥塞控制方法

TCP进行拥塞控制的算法有4种:慢开始、拥塞避免、快重传和快恢复。下面在讨论这些算法时我们假定:

(1)数据是单方向传送的,对方只传送确认报文。

(2)接收方总是有足够大的缓存空间。

4种算法

1.慢开始和拥塞避免

发送方维持一个拥塞窗口的状态变量,其大小取决于拥塞程度,并且动态变化。发送方让自己的发送窗口小于拥塞窗口(如果考虑接收方的接收能力的话,发送窗口可能小于拥塞窗口)。发送方控制拥塞窗口的原则是:只要网络没有拥塞,拥塞窗口就再增大一点,以便把更多的分组发送出去,只要出现拥塞,就减小拥塞窗口,以减少注入到网络的分组数。

下面会从“慢开始算法”讲起来讨论拥塞窗口的大小如何变化的。

慢开始

慢开始的算法思路是:当主机开始发送数据时,由于并不清楚网络的负荷情况,所以如果立即把大量数据字节注入到网络中,就有可能引起网络拥塞。因此会采用由小逐渐增大发送窗口。即在通常开始发送报文时,先将拥塞窗口cwnd的值设为一个最大报文段MSS的数值,而在每收到一个新的报文段确认后,把拥塞窗口增加至多一个MSS的数值。

发送方每收到一个确认就将窗口cwnd加1

如上图所示,开始时cwnd=1,发送方发送一个M1,接收方收到M1发送确认,发送方收到一个确认后将cwnd加1,此时cwnd=2,因此发送方发送M2和M3两个报文段,接收方收到后返回两个确认,因此cwnd增加两次,此时cwnd=4,接着发送方发送M4~M7四个报文段。依次类推。因此使用慢开始算法后,每经过一个传输轮次,拥塞窗口就加倍。

但是为了防止拥塞窗口cwnd增加过大导致网络拥塞,需要设置一个慢开始门限ssthresh,慢开始门限用法如下:

当cwnd

当cwnd>ssthresh时,停止使用慢开始算法,使用拥塞避免算法。

当cwnd=ssthresh时,既可以使用慢开始算法,也可以使用拥塞避免算法。

这里的拥塞避免算法是指让拥塞窗口缓慢的增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是像慢开始阶段那样加倍增长。

需要注意的是无论在慢开始阶段还是拥塞避免阶段,只要发送方判断网络出现拥塞(根据是没有按时收到确认),立即把慢开始门限ssthresh设为出现拥塞时的发送窗口的一半。然后发送窗口cwnd重新设为1,执行慢开始算法。目的是迅速减少主机发送到网络分组的分组数。

快重传与快恢复

快重传算法要求接收方每收到一个失序的报文段后就立即发送重复确认,如下图接收了M1和M2后,又接收到一个M4,M4属于失序报文,则发送对M2的重复确认。发送方只要连续收到三次确认重复就立即重传对方未收到的报文段M3。

快重传与快恢复

与快重传算法配合的还有快恢复算法,过程如下:

(1)当发送方连续收到三个重复确认时,就把慢开始门限ssthresh减半,这是为了防止网络拥塞,接着并不执行慢开始算法。

(2)由于上图这种情况很可能不是因为网络拥塞引起的,因此这里不执行慢开始算法(即不把拥塞窗口cwnd设为1,这样速度太慢),而是把cwnd值设置为慢开始门限ssthresh减半后的数值,然后开始执行拥塞避免算法。

5.9 TCP运输连接管理

TCP的运输连接有是三个阶段:连接建立、数据传送和连接释放。在TCP的连接过程中要解决以下三个问题:

(1)要使每一方能够确知对方的存在。

(2)要允许双方协商一些参数(如最大窗口值、是否使用窗口扩大选项和时间戳选项以及服务质量)。

(3)能够对运输实体资源进行分配。

5.9.1 TCP的连接建立

TCP建立连接的过程叫做握手,握手需要在客户和服务器之间交换3个TCP报文段。如图是三报文握手建立的连接过程:

三报文握手

假定主机A运行的是TCP客户程序,而B运行的是TCP服务器程序。最初两端的TCP进程都处于CLOSED状态。下面是建立连接的具体流程:

(1)B的TCP服务器进程先创建传输控制块TCB,准备接收客户端的连接请求,然后服务器处于监听状态。

(2)A的TCP客户端进程创建传输控制块TCB,然后向B发送连接请求报文段,首部同步位SYN=1,ACK=0,同时选择一个初始序号seq=x。(TCP规定SYN=1的报文不能携带数据,但要消耗一个序号),这时TCP客户端进入SYN-SENT(同步已发送)状态。

(3)B收到连接请求报文后,如同意连接,则向A发送确认。确认报文段中SYN=1,ACK=1,确认号ack=x+1,同时也为自己选择一个初始序号seq=y。注意,这个报文段也不能携带数据,同时需要消耗一个序号。此时,TCP服务器进入SYN-RCVD(同步收到)状态。

(4)TCP客户端进程A收到B的确认后,还要向B给出确认。确认报文段SYN=0,ACK=1,确认号ack=y+1,而自己的序号seq=x+1。(TCP规定,ACK报文段可以携带数据,但如果不携带数据则不消耗序号,因此下一个数据报文段的序号仍是seq=x+1),这时TCP连接已经建立。A进入ESTABLISHED(已建立连接状态),当B收到A的确认后,也进入ESTABLISHED状态。

A最后还要发送一次确认的原因是为了防止已经失效的连接请求报文段突然又传送到了B,因而产生错误。试想一种情况:如果只有第一次和第二次握手,第二次B向A发送的确认丢失了,此时B进入了连接建立状态,A没有收到确认,过一段时间后会再次向B发送连接请求,B收到后又会再次建立连接,白白浪费B的资源。

5.9.2 TCP连接释放

TCP连接释放过程

在图中A和B都是处于连接状态,它们的释放过程如下:

(1)A的应用进程向其TCP发送连接释放报文段,并停止再发送数据,主动关闭TCP连接。A吧连接释放报文段首部的终止控制位FIN置1,其序号seq=u,它等于前面已传送过的数据的最后一个字节的序号加1。这时A进入了FIN-WAIT-1(终止等待1)。注意LTCP规定,FIN报文即使不携带数据,也要消耗一个序号。

(2)B收到连接释放报文后,立即发送确认,确认号ack=u+1,而这个报文自己的序号为v,等于B前面已传送的数据的最后一个字节的序号加1。然后B进入CLOSE-WAIT(关闭等待)。TCP服务进程此时要通知高层应用进程。这时的TCP处于半连接状态,即A不会发送数据给B,但若B发送数据给A,A仍要接收。

(3)A收到B的确认后,就进入了FIN-WAIT-2(停止等待2),等待B发出连接释放报文。

(4)若B已经没有数据要发送了,则其应用进程通知TCP释放连接。这时B发送的报文段里FIN=1,假定此时B的序号为w,ack=u+1。这时B进入LAST-ACK(最后确认)。

(5)A收到B的释放连接报文段后,必须对此发出确认。确认报文段ACK=1,seq=u+1,ack=w+1。然后进入TIME-WAIT(时间等待)。经过2MSL后,进入CLOSE状态。

(6)B收到了A发送的确认报文段后,进入CLOSE状态。

A在TIME-WAIT状态等待2MSL(MSL,最长报文段寿命),主要是因为以下两点考虑:首先是为了保证A发送的最后一个ACK报文段能够到达B,因为这个ACK报文段可能丢失,此时B会重传连接释放报文,如果A已经关闭,则无法收到这个报文。其次,当A在发送完最后一个ACK报文段后,再经过时间2MSL,就可以使本连接持续时间内产生的所有报文段都从网络中消失。这样,下一个新连接中不会出现这种旧的连接请求报文段。

5.9.3 TCP的有限状态机

TCP有限状态机

在图中每一个方框即TCP可能具有的状态。每个方框中的大写英文字符串时TCP标准所使用的的TCP连接状态名。状态之间的箭头表示可能发生的状态变迁。箭头旁边的字表明引起这种变迁的原因,或表明发生状态变迁后又出现什么动作,在图中粗实线箭头表示对客户进程的正常变迁,粗虚线箭头表示对服务器进程的正常变迁,细线箭头表示异常变迁。

你可能感兴趣的:(计算机网络运输层两种服务)