天津废铁废钢贴吧:网络传输层工作原理

来源:百度文库 编辑:中财网 时间:2024/04/28 08:19:32

第8章 传输层

传输协议(transport protocol)是整个网络体系结构中的关键之一。本章讨论TCP/IP体系中的运输协议UDP和TCP。TCP比UDP复杂得多。最重要的是应弄清端口的概念及TCP的各种机制(如面向连接的可靠服务、序号、确认、窗口、拥塞控制等)以及TCP有关连接管理和状态图的概念。

8.1 传输协议概述

从通信和信息处理的角度.运输层向它上面应用层提供通信服务,它属于面向通信部分的最高层,同时也是用功能中的最低层、运输层只存在于通信子网以外的主机中,在

通信子网中没有运输层,如图8-所示。

下面通过图8-1的示意图来说明运输层的作用。设局域网1上的主机A和局域网2上的主机B通过互连的广域网进行通信。既然IP协议能够将源主机发送出的分组按照首部中的目的地址送交到目的主机,那么,为什么还需要再设置一个运输层呢

图8-1 传输层为相互通信的应用进程提供了逻辑通信

 

严格地讲,两个主机进行通信实际上就是两个主机中的应用进程互相通信。IP协议虽然能把分组送到目的主机,但是这个分组还停留在主饥的网络层而没有交付给主机中的应用进程(请注意:IP地址是标识在因特网中的—个主机,而不是标识主机中的应用进程)。然而一个主机中经常有多个应用进程同时分别和另一个主机中的多个应用进程通信。例如,某用户在使用浏览器查找某网站的信息时,其主机的应用层运行浏览器客户进程。如果在浏览网页的同时,还要用电子邮件给网站发送反馈意见,那么主机的应用层就还要运行电子邮件的客户进程:在图8-1中,主机A的应用进程l和主机B的应用进程3通信,而与此同时,应用进程2也和对方的应用进程4通信。运输层的—个很重要的功能就是复用和分用。应用层不同进程的报文通过不同的端口(在8.2.2节还要详细讨论端口的概念)向下交到运输层,再往下就共用网络层提供的服务。当这些报文沿着图中的虚线到达目的主机后,目的主机的运输层就使用其分用功能,通过不同的端口将报文分别交付到相应的应用进程。图8-2中两个运输层之间有一个粗的双向箭头,写明“运输层提供应用进程间的逻辑通信”。“逻辑通信”的意思是:应用进程的报文到达运输层后,从效果上看,就好像是直接沿水平方向传送到远地的运输层。当然事实上这两个应用进程之间并没有一条水平方向的物理连接。要传送的数据是沿着图中的虚线方向传送的。

从这里可以看出网络层和运输层有很大的区别。运输层为应用进程之间提供逻辑通信,但网络层是为主机之间提供逻辑通信,如图8-2所示。如果运输层只有这—点复用和分用功能,那么取消运输层而让网络层增加这一点功能也未尝不可。然而,运输层还具有网络层无法代替的许多其他重要功能。

图8-2 运输层协议和网络层协议的主要区别

其次,运输层还要对收到的报文进行差错检测。大家应当还记得,在网络层,IP数据报首部中的检验和字段,只检验首部是否出现差错而不检查数据部分。

图8-3 运输层与其上下层之间的关系的OSI表示法

再次,根据应用的不同,运输层需要有两种不同的运输协议,即面向连接的TCP和无连接的UDP,而网络层无法同时实现这两种协议。

OSI使用了简洁的抽象方法将运输层与其上下层之间的关系归纳如图8-3所示。

根据OSI的观点,运输层中向应用层提供运输服务的是运输实体。使用运输服务的是运输服务用户(也就是应用层中的各种应用进程,或应用层实体,但不是使用计算机的最终用户)。运输层中的两个对等运输实体之间的通信遵循着运输协议。运输协议保证了运输层能够向应用层提供运输服务。运输层提供的运输服务也使用了下面网络层向上提供的网络服务。TSAP和NSAP分别是运输层和网络层的服务访问点,它们都是层与层之间交换信息的抽象

接口。

我们要再次强调指出,运输层向高层用户屏蔽了下面通信子网的细节(如网络拓扑、所采用的协议等),它使应用进程看见的就是好像在两个运输层实体之间有一条端到端的逻辑通信信道,但这条逻辑通信信道对上层的表现却因运输层使用的不同协议而有很大的差别。当运输层采用面向连接的TCP协议时,尽管下面的网络是不可靠的(即只提供尽最大努力服务),但这种逻辑通信信道就相当于一条全双工的可靠信道。但当运输层采用无连接的UDP协议时,这种逻辑通信信道则是一条不可靠信道。在图8-4中我们将可靠信道画成一个管道,这意味着报文在这样的“管道”中运输时,可以做到无差错、按序(接收的顺序和发送的顺序一样)、无丢失和无重复。对不可靠信道就用一个云状网络来表示,它不具备可靠倍道的按序、无丢失和无重复的特性,但仍具有无差错的特性。只要检查出报文有差错就将其丢弃。最后再强调一下,我们说运输层提供可靠的交付,是指运输层将数据可靠地交付给接收端的应用层,但应用层是否再可靠地交付给最终用户,现在还不知道。

图8-4运输层向上提供可靠的和不可靠的逻辑通信信道

 

8.2 TCP/IP体系中的运输层

8.2.1 运输层中的两个协议

TCP/IP的运输层有两个不同的协议,如图8-5所示,它们都是因特网的正式标准。即:(1)用户数据报协议UDP(User Datagram Protocol):见[RFC 793]。

(2)传输控制协议TCP(Transmission Control Protocol):见[RFC 768]。

按照OSI的术语,两个对等运输实体在通信时传送的数据单位叫做运输协议数据单元TPDU(Transport Protocol Data Unit)。但在TCP/IP体系中,则根据所使用的协议是TCP或UDP,分别称之为TCP报文段(segment)或UDP报文或用户数据报。

UDP在传送数据之前不需要先建立连接。远地主机的运输层在收到UDP报文后,不需要给出任何确认。虽然UDP不提供可靠交付,但在某些情况下UDP是—种最有效的工作方式。TCP/IP体系中的应用服务,如DNS和NFS就使用UDP这种运输方式。

图8-5 TCP/IP 体系中的运输层协议

TCP则提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。即不提供广播或多播服务。由于TCP要提供可靠的、面向连接的运输服务,因此不可避免地增加了许多的开销,如确认、流量控制、计时器以及连接管理等。这不仅使协议数据单元的首部增大很多,还要占用许多的处理机资源。

这里还要强调两点:

(1)运输层的UDP用户数据报与网际层的IP数据报有很大的区别。IP数据报要经过互连网中许多路由器的存储转发,但UDP用户数据报是在运输层的端到端抽象的逻辑信道中传送的。这个逻辑信道虽然也是尽最大努力交付(因而不可靠),但运输层的这个逻辑信道并不经过路由器(运输层看不见路由器),因为路由器只有下三层协议而没有运输层。IP数据报虽然经过路由器进行转发,但用户数据报只是IP数据报中的数据,因此路由器看不见有用户数据报经过它。这两种数据报不能弄混。

(2)TCP连接也和网络层中的虚电路(X.25所使用的)完全不同。TCP报文段是在运输层的端到端抽象的逻辑信道中传送,但TCP连接是可靠的全双工信道,不涉及到互连网中的路由器。这些路由器根本不知道上面的运输层建立了多少个TCP连接。然而在X.25建立的虚电路所经过的交换结点中,都要保存X.25虚电路的状态信息。

8.2.2 端口的概念

UDP和TCP都使用了与应用层接口处的端口(port)与上层的应用进程进行通信。端口是个非常重要的概念,因为应用层的各种进程是通过相应的端口与运输实体进行交互。当运输层收到IP层交上来的数据(即TCP报文段或UDP用户数据报)时,就要根据其中首部的端口号来决定应当通过哪—个端口上交给应当接收此数据的应用进程。图8-6说明了端口在进程之间的通信中所起的作用。

用OSI的术语,图中的端口就是运输层服务访问点TSAPC可以看出,若没有端口,运输层就无法知道数据应当交付给应用层的哪一个进程。从这个意义上讲,端口是用来标识应用层的进程。由于使用了复用和分用技术,在运输层与网络层的交互中已看不见各种应用进程,而只有TCP报文段或用户数据报。IP层也使用类似的复用和分用技术,因而在网络层和链路层的交互中也只有IP数据报。上述概念在网络中是十分重要的。

图8-6端口在进程之间的通信中所起的作用

在运输层与应用层的接口上所设置端口是一个16 bit的地址,并用端口号进行标识。端口就是一个抽象的定位符,有时也可称为邮箱(mailbox)。端口的基本概念就是:应用层的源进程将报文发送给运输层的某个端口,而应用层的目的进程从端口接收报文。端口号只具有本地意义。即端口号只是为了标识本计算机应用层中的各进程。不同计算机中的相同端口号是没有联系的。16比的端口号可允许有64K个端口号,这个数目对一个计算机来说是足够用的。

端口号分为两类。一类是由因特网指派名字和号码公司I。ANN负责分配给—些常用的应用层程序固定使用的熟知端口(well-known port),其数值一股为0~l023,见[RFC1700]。例如,FTP用21,TELNET用23,SMTP用25,DNS用53,HTTP用80,SNMP用161,等等。“熟知”就表示这些端口号是TCP/IP体系确定并公布的,因而是所有用户进程都知道的。当一种新的应用程序出现时,必须为它指派一个熟知端口,否则其他的应用进程就无法和它进行交互。在应用层中的各种不同的服务器进程不断地检测分配给它们的熟知端口,以便发现是否某个客户进程要和和它通信。另一类则是一般端口,用来随时分配给请求通信的客户进程。

图8-8举例说明了端口的作用。设主机A使用简单邮件传送协议SMTP与主机。通信。SMTP使用而向连接的TCPC为了找到目的主机中的SMTP,主机A与主机。建立的连接要使用目的主机中的熟知端口,其端口号为25。主机A也要给自己的进程分配一个端口号,设分配的源端口号为1500。这就是主机A和主机。建立的第一连接。图中的连接画成虚线,表示这种连接不是物理连接而只是个虚连接(即逻辑连接)。

现在主机A中的另一个进程也要和主机。中的SMTP建立连接。目的端口号仍为25,但其源端口号不能与上一个连接的重复。设主机A分配的这个源端口号为1501。这是主机A和主机。建立的第二个连接。

设主机B现在也要和主机C的SMTP建立连接,端口号当然还是25。主机B选择源端口号为1500。这是和主机C建立的第三个连接。这里的源端口号与第一个连接的源端口号相同,但纯属巧合。各主机都独立地分配自已的端口号。

为了在通信时不致发生混乱,就必须把端口号和主机的IP地址结合在—起使用,在图8-8中,主机A和B虽然都使用了相同的源端口号1500.但只要查一下IP地址就可知道是哪一个主机的数据。

因此,TCP使用“连接”(而不仅仅是“端口”)作为最基本的抽象。一个连接由它的两个端点来标识。这样的端点就叫做插口(socket)或套接字。插口的概念并不复杂,但非常重要。插口包括IP地址(32 bit)和端口号(16 bit),共48 bit。插口和端口、IP地址的关系如图8-9所示。

在整个因特网中,在运输层通信的一对插口必须是惟一的。例如:对图8-8中的连接1的一对插口是:

(131.6.23.13,1500)和(130.42.85.15,25)

意思是:IP地址为131.6.23.13的主机用端口1500和IP地址为130.42.85.15的主机端口25建立了连接1,而连接2的一对插口是:

(131.6.23.13,1501和(230.42.85.15,25)

意思是:IP地址为131.6.23.13的土机用端口1501和IP地址为130.42.85.15的主机的端口25建立了连接2。

上面的例子是使用面向连接的TCP。若使用无连接的DDP,虽然在相互通信的两个进程之间没有一条虚连接,但发送端UDP一定有一个发送端口而在接收端UDP一定有—个接收端口,因而也同样可使用插口的概念。这样才能区分多个主机中同时通信的多个进程。

值得注意的是,插口这个名词很容易让人将一些概念弄混淆,因为同一个名词socket有多种不同的意思。例如:

(1)允许应用程序访问连网协议的应用编程接口API(Application Programming Interface),也就是在运输层和应用层之间的—种接口,称为socket API,并简称为socket。

(2)在socket API中使用的—个函数名也叫做socket。

(3)调用socket函数的端点称为socket,如“创建—个数据报socket”。

(4)socket函数的返回值称为socket描述符,可简称为socket。

(5)在操作系统内核中连网协议的Berkeley实现称为socket实现。

上面的这些socket的意思都和本章中的socket(指IP地址和端口号的组合)不同。

8.3 用户数据报协议UDP

本节将分别介绍UDP和TCP的要点。由于UDP很简单,因而本节以讨论TCP为重点。

8.3.1 用户数据报的用途

用户数据报协议UDP只在IP的数据报服务之上增加了很少—点的功能,这就是端口的功能(有了端口,运输层就能进行复用和分用)和无差错检测的功能。虽然UDP用户数据报只能提供不可靠的交付,但UDP在某些方面有其特殊的优点,例如:

(1)发送数据之前不需要建立连接(当然发送数据结束时也没有连接需要释放),因而减少了开销和发送数据之前的时延。

(2)UDP没有拥塞控制,也不保证可靠交付,因此主机不需要维持具有许多参数的、复杂的连接状态表。

(3)UDP用户数据报只有8个字节的首都开销,比TCP的20个字节的首部要短。

(4)由于UDP没有拥塞控制,因此网络出现的拥塞不会使源主机的发送速率降低。这对某些实时应用是很重要的。很多的实时应用(如IP电话、实时视频会议等)要求源主机以恒定的速率发送数据,并且允许在网络发生拥塞时丢失一些数据,但不允许数据有太大的时延。UDP正好适合这种要求。

虽然某些实时应用需要使用没有拥塞控制的UDP,但当很多的源主机同时都向网络发送高速率的实时视频流时,网络就有可能发生拥塞,结果大家都无法正常接收。因此“UDP不具有拥塞控制功能”,可能会引起网络产生严重的拥塞问题。

还有些使用UDP的实时应用需要对UDP的不可靠的传输进行适当的改进以减少数据的丢失。在这种情况下,应用进程本身可在不影响应用的实时性的前提下增加一些提高可靠性的措施,如采用前向纠错或重传已丢失的报文。

 

8.3.2 用户数据报的格式

用户数据报UDP有两个字段:数据字段和首都字段。首部字段很简单,只有8个字节如图8-11所示,由4个字段组成,每个字段都是两个字节。各字段意义如下所述。

(1)源端口字段:源端口号。

(2)目的端口字段:目的端口号。

(3)长度字段:UDP用户数据报的长度。

(4)检验和字段:防止UDP用户数据报在传输中出错。

图8-7 UDP用户数据报的首部和伪首部

UDP用户数据报首都中检验和的计算方法有些特殊。在计算检验利时在UDP用户数据报之前要增加12个字节的伪首部。所谓“伪首部”是因为这种伪首部并不是UDP用户数据报真正的首部。只是在计算检验和时,临时和UDP用户数据报连接在一起,得到一个过渡的UDP用户数据报。检验和就是按照这个过渡的UDP用户数据报来计算的,伪首部既不向下传送,也不向上递交。图8-7的最上面给出了伪首部各字段的内容。

UDP计算检验和的方法和计算IP数据报首都检验和的方法相似。在发送端,首先是先将全零放入检验和字段。再将伪首部以及UDP用户数据报(现在要包括数据字段]看成是由许多16 bit的字串接起来。若UDP用户数据报的数据部分不是偶数个字节则要填入一个全零字节(但此字节不发送)。然后按二进制反码计算出这些16 bit字的和。将此和的二进制反码写入检验和字段后,发送此UDP用户数据报。在接收端,将收到的UDP用户数据报连同伪首部(以及可能的填充全零字节)一起,按二进制反码求这些16 bit字的和。当无差错时其结果应为全1。否则就表明有差错出现,接收端就应将此UDP用户数据报丢弃(也可以上交给应用层,但附上出现了差错的警告)。图8-12给出了一个计算UDP检验和的例子。这里假定用户数据报的长度是15字节,因此要添加一个全0的字节,读者可以自己检验一下在接收端是怎样对检验和进行检验的。不难看出,这种简单的差错检验方法的检错能力并不强,但它的好处是简单,处理起来较快。

伪首都的第3字段是全0,第4个字段是IP首部中的协议字段的值。以前已讲过,对于UDP,此协议字段值为17,第5字段是UDP用户数据报的长度。因此我们可以看出,这样的检验和,既检查了UDP用户数据报的源端口号、日的端门号以及UDP用户数据报的数据部分,又检查了IP数据报的源IP地址和目的址址。

8.4 传输控制协议TCP

TCP/IP体系中面向连接的运输层协议,它提供全双工的可靠交付的服务。一定要记住:TCP与UDP最大的区别就是TCP是面向连接的,而UDP是无连接的。下面先介绍TCP的报文段首部的格式,然后再讨论保证数据传送可靠、按序、无丢失和元重复的一些机制。

传输的可靠是由于使用了序号和确认。当TCP发送一报文段时,它同时也在重传队列中放入一个副本。若收到确认,则删除此副本。若在计时器时间到之前没有收到确队,则重传此报文段。TCP的确认并不保证数据已交付给端用户,这是接收TCP的责任。

图8-11 TCP报文段的首部

8.4.1 TCP报文段的首部

一个TCP报文段分为首部和数据两部分,如图8-11所示。应当指出,TCP的全部功能都体现在它的首都的各字段。本节先大致介绍各字段的作用,然后在后续的几节还要结合相关的字段详细讨沦TCP的主要机制。

TCP报文段首都的前20个字节是固定的,后面有4 N字节是根据需要而增加的选项(N必须是整数)。因此TCP首部的最小长度是20字节。首部固定部分各字段的意义如下所述。

(1)源端口和目的端口

各占两个字节,前面已经讲过,端口是运输层与应用层的服务接口。16 bit的端口号加上32 bit的IP地址,构成了插口(socket),它相当于运输层服务访问点TSAP的地址(总共是48bit)。这些端口用来将若干高层协议向下复用,也用来将运输层协议向上分用。

(2)序号

占4字节。TCP是面向数据流的,TCP传送的报文可看成为连续的数据流,其中每一个字节都对应于一个序号。首部中的“序号”则指的是本报文段所发送的数据中第一个字节的序号,例如,某报文段的序号字段的值是30l,而携带的数据共100字节,则本报文段的数据的第一个字节的序号是301,而最后一个字节的序号是400。这样,下一个报文段的数据序号应当从401开始,因而下一个报文段的序号字段的值应为401。

(3)确认序号

占4字节,是期望收到对方的下—个报文段的数据的第一个字节的序号,也就是期望收到的下—个报文段首部的字号字段的值。例如,正确收到了一个报文段,其序号字段的值是501,而数据长度是200字节,这就表明序号在501~700之间的数据均已正确收到。因此在响应的报文段中应将确认序号置为701。请注意:确认序号既不是501也不是700。

由于序号字段有32 bit长,可对4 GB(即4千兆字节)的数据进行编号,这样就可保证当序号重复使用时,旧序号的数据早已在网络中消失了。

(4)数据偏移

占4bit,它指出数据开始的地方离TCP报文段的起始处有多远。这实际上就是TCP报文段首都的长度。由于首部长度不固定(因首部中还有长度不确定的选项字段),因此致据偏移字段是必要的。但应注息,“数据偏移”的单位不是字节,而是32 bit字(即4字节字)。由于4 bit能表示的最大十进制数是15,因此数据偏移的最大值是60字节,这也是TCP首部的最大长度。

(5)保留

占6 bit,保留为今后使用,但目前应置为0。

下面有6个比特是说明本报文段性质的控制比特,它们的意义如下。

(6)紧急比特URG(URGent)

当URG=1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据),而不要按原来的排队顺序来传送。例如,已经发送了很长的一个程序要在远地的主机上运行。但后来发现了一些问题,需要取消该程序的运行。因此用户从键盘发出中断命令(Control+C)。如果不使用紧急数据,那么这两个字符将存储在接收TCP缓存的末尾。只有在所有的数据被处理完毕后这两个字符才被交付到接收应用进程。这样做就浪费了许多时间。

当使用紧急比特并将URG置1时,发送应用进程就告诉发送TCP这两个字符是紧急数据。于是发送TCP就将这两个字符插入到报文段的数据的最前面,其余的数据都是普通数据。这时要与首部中第五个32 bit字中的一半“紧急指针”(Urgent Pointer)字段配合使用。紧急指针指出在本报文段中的紧急数据的最后一个字节的序号。紧急指针使接收方知道紧急数据共有多少个字节。紧急数据到达接收端后,当所有紧急数据都被处理完时,TCP就告诉应用程序恢复到正常操作。值得注意的是,即使窗口为零时也可发送紧急数据。

(7)确认比特ACK

只有当ACK=1时确认序号字段才有效。当ACK=0时,确认序号无效。

(8)推送比特PSH(PuSH)

当两个应用进程进行文互式的通信时,有时在一端的应用进程希望在键入一个命令后立即就能够收到对方的响应。在这种情况下,TCP就可以使用推送(push)操作。这时,发送端TCP将推送比特PSH置1,并立即创建一个报文段发送出上。接收TCP收到推送比特置1的报文段,就尽快(即“推送”向前)交付给接收应用进程,而不再等到整个缓存都填满了后再向上交付。PSH比特也可叫做急迫比特。

虽然应用程序可以选择推推送操作,但抵达操作还是往往不被人们使用。TCP可以选择或不选择这个操作。

(9)复位比特RST(ReSeT)

当RST=1时,表明TCP连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。复位比特还用来拒绝一个非法的报文段或拒绝打开一个连接。复位比特也可称为重建比特或重置比特。

(10)同步比特SYN

在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使SYN=1和ACK=1。因此,同步比特SYN置为1,就表示这是一个连接请求或连接接受报文。关于连接的建立和释放,后面还要进行讨论。

(11)终止比特FIN(FINal)

用来释放一个迎接,当FIN=1时,表明此报文段的发送端的数据已发送完毕,并要求释放运输连接。

(12)窗口

占2字节。窗口字段用来控制对方发送的数据量,单位为字节。大家知道,计算机网络经常是用接收端的接收能力的大小来控制发送端的数据发送量。TCP也是这样。TCP连接的一端根据自己缓存的空间大小确定自己的接收窗口大小,然后通知对方来确定对方的发送窗口。假定TCP连接的两端是A和B。若A确定自己的接收窗口为WIN,则将窗口WIN的数值写在A发送给B的TCP报文段的窗口字段中,这就是告诉B的TCP,“你(B)在未收到我(A)的确认时所能够发送的数据量就是从本首部中的确认序号开始的WIN个字节。”所以A所确定的WINA是A的接收窗口,同时也就是B的发送窗口。例如,A发送的报文段首部中的窗口WIN=500,确认序号为201,则表明B可以在未收到确认的情况下,向A发送序号从201~700的数据。B在收到此报文段后,就以这个窗口数值WIN作为B的发送窗口。但应注意,B所发送的报文段中的窗口字段则是根据B的接收能力来确定A的发送窗口,不要弄混。

(13)检验和

占2字节。检验和字段检验的范围包括首部和数据这两部分。和UDP用户数据报一样,在计算检验和时,要在TCP报文段的前面加上12字节的伪首都。伪首部的格式与图8-10中UDP用户数据报的伪首部一样。但应将伪首部第四个字段中的17放为6(TCP的协议号是6),将第五字段中的UDP长度改为TCP长度。接收端收到此报文段后,仍要加上这个伪首都来计算检验和。若使用IPV6,则相应的伪首部也要改变。

(14)选项

长度可变。TCP只规定了一种选项,即最大报文段长度MSS(Maximum Segment Size)。MSS告诉对方TCP:“我的缓存所能接收的报文段的数据字段的最大长度是MSS。”与没有选项时,TCP的首部长度是20字节。

MSS的选择并不简单。若选择较小的MSS长度,网络的利用率就降低。设想在极端的情况下,当TCP报文段只含有1字节的数据时,在IP层传输的数据报的开销至少有40字节(包括TCP报文段的首部和IP数据报的首都)。这样,对网络的利用率就不会超过1/41,到了数据链路层还要加上一些开销。但反过来,若TCP报文段非常长,那么在IP层传输时就有可能要分解成多个短数据报片。在目的站要将收到的各个短数据报片装配成原来的TCP报文段。当传输出错时还要进行重传。这些也都会使开销增大。一般认为,MSS应尽可能大些,只要在IP层传输时不需要再分片就行。在连接建立的过程中,双方都将自己能够支持的MSS写入这一字段。在以后的数据传送阶段,MSS取双方提出的较小的那个数值:若主机未填写这项,则MSS的默认值是536字节长。因此,所有要因特网上的主机都能接受的报文段长度是536+20=556字节。

8.4.2 TCP的数据编号与确认

TCP协议是面向字节的。TCP将所要传送的整个报文(这可能包括许多个报文段)看成是一个个字节组成的数据流,并使每一个字节对应于一个序号。在连接建立时,双方要商定初始序号。TCP诲队所发送的报文段的首部中的序号字段数值表示该报文段中的数据部分的第一个字节的序号。

TCP的确认是对接收到的数据的最高序号(即收到的数据流中的最后一个序号)表示确认。但接收端返回的确认序号是已收到的数据的最高序号加1。也就是说,确认序号表示接收端期望下次收到的数据中的第一个数据字节的序号。

由于TCP连接能提供全双工通信,因此通信中的每一方都不必专门发送确认报文段,而可以在传送数据时顺便把确认信息捎带传送,这样做可以提高传输效率。

在发送端,TCP是怎样决定发送个报文段的时机呢

TCP有三种基本机制来控制报文段的发送。第一种机制是TCP维持一个变量,它等于最大报文段长度MSS,只要发送缓存从发送进程得到的数据达到MSS字节时,就组装成—个TCP报文段,然后发送出去。第二种机制是发送端的应用进程指明要求发送报文段,即TCP支持的推送(push)操作。第三种机制是发送端的一个计时器时间到了,这时就把当前已有的缓存数据装入报文段发送出去。

但是,如何控制TCP发送报文段的时机仍然是一个较为复杂的问题。

例如,一个交互式用户使用一条TELNET连接(运输层为TCP协议)。设用户只发—个字符。加上20字节的首部后,得到21字节长的TCP报文段。再加上20字节的IP首都,形成41字节长的IP数据报。在接收端TCP立即发出确认,构成的数据报是40字节长(假定没有救据发送)。若用户要求远地主机回送这一字符,则又要发回41字节长的IP数据报和40字节长的确认IP数据报。这样,用户仅发一字符时线路是就需传送总长度为162字节共4个报文段。当线路带宽并不富裕时,这种传送方法的效率的确不高。因此应适当推迟发回确认报文,并尽量使用捎带确认的方法。

在TCP的实现中广泛使用Nagle算法[NAGL84]:算法是:若发送端应用进程将欲发送的数据逐个字节地达到发送端的TCP缓存,则发送端就将第一个字符(—个字符的长度是一个字节)发送出去,将后面到达的字符将都缓存起来。当接收端收到对第一个字符的确认后,再将缓存中的所有字符装成一个报文段发送出去,同时继续对随后到达的字符进行缓存。只有在收到对前一个报文段的确认时才继续发送下一个报文段。当字符到达较快而网络速率较慢时,用这样的方法可明显的减少所用的网络带宽,算法还规定,当到达的字符已达到窗口大小的一半或己达到报文段的最大长度时,就立即发送一个报文段。

但有时不宜采用Nagle算法。例如在因特网上使用X Windows,并将鼠标移动的信息传到远地主机。若采用Nagle算法会使用户感到无法忍受。这时最好关闭这个算法。

另一个问题叫做糊涂窗口综合症(silly window syndrome)[RFC 813],有时也会使TCP的性能变坏。设想这种情况:接收端的缓存已满,而交互的应用进程一次只从缓存中读取一个字符(这样就在缓存产生1个字节的空位,然后向发送端发送确认,并将窗口设置为1个字节(但发送的数据报是40字节长)。接着,发送端又传来1个字符(但发来的IP数据报是41字节长。接收端发回确认,仍然将窗口设置为一个字节。这样进行下去,网络的效率将会很低。

要解决这个问题,可让接收端等待一段时间,使得或者缓存已能有足够的空间容纳—个最长的报文段,或者缓存已有一半的中间处于空的状态。只要出现这两种情况之一,就发出确认报文,并向发送端通知当前的窗口大小。此外,发送端也不要发送太小的报文段,而是将数掘积累成足够大的报文段,或达到接收端缓存的空间的—半大小。

上述两种方法可配合使用。使得在发送端不发送很小的报文段的同时,接收端也不要在缓存刚刚有了一点小的空位置就急忙将一个很小的窗口大小通知给发送端。

若发送方在规定的设置时间内没有收到确认,就要将未被确认的报文段重新发送。接收方若收到有差错的报文段,则丢弃此报文段(不发达否认信息)。若收到重复的报文段,也要将其丢弃,但要发回(或捎带发回)确认信息。这与数据链路层的情况相似。

若收到的报文段无差错,只是未按序号,那么该如何处理?TCP对此未作明确规定,而是让TCP的实现者自行确定。或者将不按序的报文段丢弃,或者先将其暂存于接收缓存内,待所缺序号的报文段收齐后再一起上交应用层。如有可能,采用后—种策略对网络的性能会更好些。例如,发送端每个报文中含有100字节的数据,且一连发送了8个报文段,其序号分别为1,l01,201,…,701。设接收端正确收到了其中的7个,而未收到序号为201的报文段。接收端可以将序号为30l~701的5个报文段先进行暂存,而发回确认序号为201的报文段(即序号为200及这以前的都已正确收到了)。当发送端重传的序号为201的报文段正确到达接收端后,接收端就发回确认序号为801的确认,因而提高了传输效率。

8.4.3 TCP的流量控制与拥塞控制

为了提高报文段的传输效率,TCP采用大小可变的滑动窗口进行流量控制。窗口大小的单位是字节。在TCP报文段首部的窗口字段写入的数值就是当前给对方设置的窗口数值。发送窗口在连接建立时由双方商定。但在通信的过程中,接收端可根据自己的资源情况,随时动态地调整对方为发送窗口(可增大或减小)。这种由接收端控制发送端的做法,在计算机网络中经常使用。图8-12表示的是在TCP中使用的窗口概念。在TCP中接收端的接收窗口总是等于发送端的发送窗口(因为后者是由前者确定的),因此—般就只使用发送窗口这个词汇。这一点和数据链路居HDLC中的滑动窗口很不一样。在不使用选择重传ARQ时,通接收双方的接收窗口都 是1,而发送窗口是由帧编号的位数确定的。

图7-12 TCP中的窗口概念

 

图8-13 利用可变窗口进行流量控制举例

图8-12(a)表示发送端要发送900字节长的数据,划分为9个100个节长的报文段,对方确定的发送窗口为500字节。发送端只要收到了对方的确认,发送窗口就可前移。发送端的TCP要维护一个指针。每发送一个报文段,指针就向前移动—个报文段的距离。当指针移动到发送窗口的最右端(即窗口前沿)时就不能再发送报文段了。

图8-12(b)表示发送端已发送了400字节的数据,但只收到对前200字节数据的确认,同时窗口大小不变,我们注意到,现在发送端还可发送300字节。

图8-12(C)表示发送端收到了对方对前400字节数据的确认,但窗口减小到400字节,于是,发送端还可发送400字节的数据。

下面通过图8-13的例子说明利用可变窗口大小进行流量控制。

设主机A 向主机B发送数据。双方确定的窗口值是400。再设每一个报文段为100字节长,序号的初始值为1(见8-16图中第一个箭头上的SEQ=1)。图8-16中右边的注释可帮助理解整个的过程。我们应注意到,主机B进行了3次流量控制。第一次将窗口减小为300字节,第二次又减为200字节,最后减至0,即不允许对方再发送数据了。这种暂停状态将持续到主机B重新发出一个新的窗口值为止。

实现流量控制并非仅仅为了使接收端来得及接收。如果发送端发出的报文过多会使网络负荷过重。由此会引起报文段的时延增大。但报文段时廷的增大,将使主机不能及时地收到确认。因此会重传更多的报文段,而这又会进一步加剧网络的拥塞。为了避免发生拥塞,主机应当降低发送速率。

可见发送端的主机在发送数据时,既要考虑到接收端的接收能力,又要使网络不要发生拥塞。因而发送端的发送窗口应接以下方式确定:

发送窗口=Min[通知窗口,拥塞窗口] (8-1)

这里

通知窗口(advertised window)是接收端根据其接收能力许诺的窗口值,是来自接收端的流量控制。接收端将通知窗口的值放在TCP报文的首部中,传送给发送端。

拥塞窗口(congestion window)是发送端根据网络拥塞情况得出的窗口值,是来自发送端的流量控制。

(8-1)式表明,发送端的发送窗口取“通知窗口”和“拥塞窗口”中的较小的一个。在未发生拥塞的稳定工作状态下,接收端通知的窗口和拥塞窗口是一致的。

为了更好地进行拥塞控制,因特网标准推荐使用以下三种技术,即慢启动(slow-start)、加速递减(multiplicative decrease)和拥塞避免(congestion avoidance)。使用这些技术的前提是:由于通信线路带来的误码而使得分组丢失的概率很小(远小于1%)。因此只要出现分组丢失或迟延过长而引起超时重传,就意味着在网络的某处出现了拥塞。实现步骤如下所述。

(1)当一个连接初始化时,将拥塞窗口置为1(即窗口允许发送1个报文段)、并设置慢启动的门限窗口值。

(2)发送端的发送窗口不能超过拥塞窗口和通知窗口的最小值。现在假定接收端不进行流量控制。

(3)发送端若收到了对所有发出的报文段的确认,就在下一次发送时将拥塞窗口加倍,可见拥塞窗口从1开始,把指数规律增长。若出现了超时,则将当时的拥塞窗口减半,作为新的门限窗口值,同时拥塞窗口再次变为1。

(4)拥塞窗口重新从1开始按指数规律增长。但当增长到新的门限窗口值时,就每次只将拥塞窗口加1,使拥塞窗口按线性规律增长。当网络又出现超时,仍重复上述过程。

(5)从以上讨论可看出,“慢启动”是指每出现一次超时,拥塞窗口都降低到1,使报文段慢慢注入到网络中。不过这个名词不太准确,因为拥塞窗口增长的比率并不很慢。“加速递减”是指每出现一次超时,就将门限窗口值减半。若超时频繁出现,则门限窗口减小的速率是很快的。“拥塞避免”是指当拥塞窗口增大到门限窗口值时,就将拥塞窗口指数增长速率降低为线性增长速率,避免网络再次出现拥塞。

采用这样的流量控制方法使得TCP的性能有明显的改进[STEV94][RFC2581]。

8.4.4 TCP的重传机制

重传机制是TCP中最重要和最复杂的问题之一。TCP每发送一个报文段,就设置一次计时器。只要计时器设置的重传时间已经到了但还没有收到确认,就要重传这一报文段。

出于TCP的下层是一个互连网环境,发送的报文段可能只经过一个高速率的局域网,但也可能是经过多个低速率的局域网,并且数据报所选择的路由还可能会发生变化。图8-17画出了数据链路层和运输层的往返时延概率分布的对比。往返时延就是从数据发出到收到对方的确认所经历的时间。对于数据链路层,其往返时延的方差很小,因此将超时时间设置为如8-17图中的T1即可。但对于运输层来说,其往返时延的方差很大。若将超时时间设计为图8-17中的T2,则很多报文段的重传时间太早,因而给网络增加了许多不应有的负荷。但若将超时时间选为图中的T3,则显然全使网络的传输效率降低很多。

那么,运输层的超时器的重传时间究竟应设置为多大呢

TCP采用了一种自适应算法。这种算法记录每一个报文段发出的时间、以及收到相应的确认报文段的时间。这两个时间之差就是报文段的往返时延。将各个报文段的往返时延样本加权平均,就得出报文段的平均往返时延T,每测量到一个新的往返时间样本,就接下式重新计算一次平均往返时延:

平均往返时延T=a(旧的往返时延T))+(1-a)(新的往返时延样本) (8-2)

在上式中,0

显然,计时器设置的重传时间应略大于上面得出的平均往返时延,即

重传时间=B(平均往返时延) (8-3)

这里B是个大于1的系数,实际上,系数B是很难确定的,若取B很接近于1,发送端可以很及时地重传丢失的报文段,因此效率得到提高。但若报文段并未丢失而仅仅是增加了一点时延,那么过早地重传未收到确认的报文段,反而会加重网络的负担。因此TCP原先的标准推荐将B值取为2。但现在已有了更好的办法。

上面所说的往返时间的测量,实现起来相当复杂,试看下面的例子。

如图8-17所示,发送出一个TCP报文段1、设定的重传到了,但还没有收到确认。于是重传此报文段,即图中的报文段2,后来收到了确认报文段ACK。现在的问题是:如何判出此确认报文段是对原来的报文段1的确认,还是对重传的报文段2的确认?由于重传的报文段2和原来的报文段1完全一样,因此源站在收到确认后,就无法做出正确的判断了。

图8-17 收到的确认报文段ACK是对哪一个报文段的确认

若收到的确认是对重传报文段2的确认,但被源站当成是对原来的报文段1的确认,那么这样计算出的往返时延样本和重传时间就会偏大。如果后面再发送的报文段又是经过重传后才收到确认报文段,那么按此方法得出的重传时间就越来越长。

同样,若收到的确认是对原来的报文段1的确认,但被当成是对重传报文段2的确认,则由此计算出的往返时廷样本和重传时间都会偏小。这就必然更加频繁地导致报文段的重传这样就有可能使重传时间越来越短。

根据以上所述,Karn提出了一个算法:在计算平均往返时延时,只要报文段重传了,就不采用其往返时延样本。这样得出的平均往返时延和重传时间当然就较准确。

但是,这又引起新的问题。设想出现这样的情况:报文段的时延突然增大了很多。因此在原来得出的重传时间内,不会收到确认报文段,于是就重传报文段。但根据Karn算法,不考虑重传的报文段的往返时延样本。这样,重传时间就无法更新。

因此,对Karn算法进行修正的方法是:报文段重传一次,就将重传时间增大一些,

新的重传时间=Y(旧的重传时间) (8-4)

系数Y的典型值是2,当不再发生报文段的重传时,才根据报文段的往返时延更新平均往返时延和重传时间的数值。实践证明,这种策略较为合理。

8.4.5 TCP的运输连接管理

TCP是面向连接的协议。运输连接的建立和释放是每一次面向连接的通信中必不可少的过程。运输连接的管理就是使运输连接的建立和释放都能正常地进行。

在连接建立过程中要解决以下三个问题。

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

(2)要允许双方协商一些参数(如最大报文段长度,最大窗口大小,服务质量等)。

(3)能够运输实体资源(如缓存大小,连接表中的项目等)进行分配。

TCP的连接和建立都是采用客户服务端方式。主动发起连接建立的进程叫做客户(client)。而被动等待正接建立的进程叫服务器(server)。

图8-18用三次握手建立 TCP 连接

 

设主机B中运行一个服务器过程,如图8-18所示,它先发出一个被动打开(passive open)命令,告诉它的TCP要准备接受客户进程的连接请求。然后服务器进程就处于“听”(listen)的状态,不断检测是否有客户进程要发起连接请求,如有,即做出响应。

 

设客户进程运行在主机A中。它先向其TCP发出主动打开(active open)命令,表明要向某个IP地址的某个端口建立运输连接。

主机A的TCP向主机B的TCP发出连接请求报文段,其首部的同步比特SYN应置为1,同时选样—个序号x.表明在后面传送数据时的第一个数据字节的序号是x。在图8-19中,一个从A到B的箭头上标有“SYN,SEQ=x”就是这个意思。

主机B的TCP收到连接请求报文段后,如同意,则发回确认。在确认报文段中应将SYN

置为1,确认序号应为x+1,同时也为自己选择一个序号y。

主机A的TCP收到此报文段后,还要向B给出确认,其确认序号为y+1。

运行客户进程的主机A的TCP通知上层应用进程,连接已经建立(或打开)。

当运行服务器进程的主机B的TCP收到主机A的确认后,也通知其上层应用进程,连接已经建立。

连接建立采用的这种过程叫做三次握手(there-way handshake),或三次联络。

为什么要发送这第三个报文段呢 这主要是为了防止己失效连接请求报文段突然又传送到了主机B,因而产生错误。

所谓“已失效的连接请求报文段”是这样产生的。考虑这样一种情况。主机A发出连接请求,但因连接请求报文丢失而未收到确认。主机A于是再重传—次。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接。主机A共发送了两个连接请求报文段,其中的第二个到达了主机 B 。

图8-19 TCP 连接释放的过程

现假定出现另一种情况,即主机 A发出的第一个连接请求报文段并没有丢失,而是在某些网络结点滞留的时间太长,以致延误到在这次的连接释放以后才传送到主机B。本来这是一个已经失效的报文段。但主机B收到此失效的连接请求报文段后,就误认为是主机A又发出—次新的连接请求,于是就向主机A发出确认报文段,同意建立连接。

主机A由于并没有要求建立连接,因此不会理睬主机B的确认,也不会向主机B发送数据,但主机B却以为运输连接就这样建立了,并一直等待主机A发来数据。主机B的许多资源就这样白白浪费了。

 

采用三次握手的办法可以防止上述现象的发生。例如在刚才的情况下,主机A不会向主机B的确认发出确认。主机B收不到确认,连接就建立不起来。

在数据传输结束后,通信的双方都可以发出释放连接的请求。

设图8-19 中的丰机A的应用进程先向其TCP发出连接释放请求,并且不再发送数据。TCP通知对方要释放从A到B这个方向的连接,将发往主机B的TCP报文段首部的终止比特FIN置1,其序号x等于前面已传送过的数据的最后一个字节的序号加l。

主机B的TCP收到释放连接通知后即发出确认,其序号为x+1,同时通知高层应用进程,如图8-19中的箭头①所示。这样,从A到B的连接就释放了,连接处于半关闭(half-close)状态,相当于主机A向主机B说:“我已经没有数据要发送了。但你如果还发送数据,我仍接收。”

此后,主机B不再接收主机A发来的数据。但若主机B还有一些数据要发往主机A,则可以继续发送。主机A只要收到数据,仍应向主机B发送确认。

在主机B向主机A的数据发送结束后,其应用进程就通知TCP释放连接,如图8-20中的箭头②所示。主机B发出的连接释放报文段必须将终止比特FIN置1,并使其序号y等于前面已传送过的数据的最后—个字节的序号加1,还必须重复上次已发送过的ACK=x+1。主机A必须对此发出确认,给出ACK=y+1,这样才将从B到A的反方向连接释放掉。主机A的TCP再向其应用进程报告,整个连接已经全部释放。

由此可见,上述连接释放过程和连接建立时的三次握手在本质上是一致的。

习 题

1.试说明运输层的作用。网络层提供数据报或虚电路服务对面的运输层有何影响

2.试用示意图来解释运输层的复用。一个给定的运输连接能否分裂成许多条虚电路?请解释之。画图说明许多个运输用户复用到一条运输连接上,而这条运输连接又复用到若干条网络连接(虚电路)上。

3.解释为什么突然释放运输连接就可能会丢失用户数据而使用TCP的连接释放方法就可保证不丢失数据。

4.试用具体例子说明为什么在运输连接建立时要使用三次握手。说明如不这样做可能会出现什么情况。

5.—个TCP报文段中的救据部分最多为多少个字节 为什么

6.主机A和B使用TCP通信。在B发送过的报文段中,有这样连续的两个:ACK=120和ACK=100。这可能吗(前一个报文段确认的序号还大于后一个的)?试说明理由。

7.在使用TCP传送数据时,如果有一个确认报文段丢失了,也不一定会引起对方数据的重传。试说明理由(可结合上一题讨论)。

8.在8.4.1节曾讲过,若收到的报文段无差错,只是未按序号,则TCP对此未作明确规定。何是让TCP的实现者自行确定。试讨论两种可能的方法的优劣:(1)将不按序的所文段丢弃;(2)允将不按序的报文段暂存于接收缓存内,待所缺序号的报文段收齐后再一块上交应用层。

9.设TCP使用的最大窗口为64KB,即64x]024字节,而传输信道的带宽可认为是不受限制的。总报文段的平均往返时延为20 ms,问所能得到的最大吞量是多少?

10.试计算一个包括5段链路的运输连接的单程端到端时延。5段链路程中有2段是卫星链路。每条卫星链路又由上行链路和下行链路两部分组成。可以取这两部分的传播时延之和为250ms。每一个局域网的范围为1500 km,其传播时延可按150000km/s来计算。各数据链路速率为48 Kbit/s,帧长为960 bit。

11.重复上题,但假定其中的一个陆地上的广域网的传输时延为150 ms。

12.什么是Karn算法 在TCP的重传机制中,若不采用Karn算法,而是在收列确认时都认为是对重传报文段的确认,那么由此得中的往返时延样本和重作时间都会偏小,试问:重传时间最后会减小到什么程度

l3.若一个应用进程使用运输层的用户数据报UDPC但继续向下文给IP层后,又封装成IP数据报。既然都是据报,是否可以跳过UDP而直接交给IP层?UDP有没有提供IP没有提供的功能

14.使用TCP对实时话音业务的传输有没有什么问题 使用UDP在传送文件时会有什么问题?

l5.TCP在进行流量控制时是以分组的丢失作为产生拥塞的标志。有没有不是因拥塞而引起的分组丢失的情况 如有,请举出三种情况。

16.一个应用程序用UDP,到了IP层将数据报再划分为4个数据报片发送出去。结果前两个数据报片丢失,后两个到达目的站。过了一段时间应用进程重传UDP,而IP层仍然划分为4个数据报片来传送,结果这次前两个到达目的站而后两个丢失。试问:在目的站能否将这两次传输的4个数据报片组装成为完整的数据报?假定目的站第—次收到的后两个数据报片仍然保存在目的站的缓存中。

17.为什么在TCP首都中有一个首部长度字段,而UDP的首都中就没有这个字段

l8.一个UDP用户数据报的数据字段为8192字节,要使用以太网来传送、试问应当划分为几个数据报片 说明每一个数据报片的数据字段长度和片偏移字段的值。

19.网络允许的最大报文段长度为128字节,序号用8 bit表示,报文段在网络中的生存时间为30秒。试求每一条TCP连接所能达到的最高数据率。

20.一个TCP连接下面使用256 Kbit/s的链路,其端到端时延为128 ms。经测试,发现吞吐量只有120kbit/s。试问发送窗口是多少