Login
升级VIP 登录 注册 安全退出
当前位置: 首页 > word文档 > 其他文档 > 第6章-传输层-5月8日

第6章-传输层-5月8日

收藏

本作品内容为第6章-传输层-5月8日,格式为 doc ,大小 628224 KB ,页数为 60页

第6章-传输层-5月8日


('第6章传输层位于应用层和网络层之间的传输层是分层网络体系结构的关键层次。本章讨论传输层的基本功能及其协议机制,并且介绍了TCP/IP体系结构中的传输层协议TCP和UDP。6.1传输层的基本功能传输层是OSI模型的第四层,是整个网络体系的核心,它的主要职能是在源计算机到目的计算机之间提供可靠的、经济的数据传送服务,而且独立于所使用的物理网络,对于一些特殊的应用,某些传输层协议也提供高效的但不可靠的数据传送服务。使用传输服务的实体可以是会话实体,也可以直接是应用实体。6.1.1传输层端到端通信的概念从本质上说,由物理层、数据链路层和网络层组成的通信子网为网络环境中的主机提供点对点通信服务,而传输层是为网络环境中的主机应用层应用进程提供端到端进程通信服务。通信子网只提供一台机器到另一台机器之间的通信,不会涉及到程序或进程的概念。端到端信道由一段段的点对点信道构成,端到端协议建立在点对点协议上,提供应用程序进程之间的通信手段。传输层端到端通信与网络层的点对点通信的关系如图6-1所示。如前所述,从网络体系结构的角度,传输层既是面向通信的最高层,又是属于用户功能的最低层,它向上面的应用层提供了通信服务。传输层的基本功能是利用图6-1传输层端到端通信的基本结构通信子网为两台主机的应用进程之间,提供端到端的性能可靠、价格合理、透明传输的通信服务。图6-1表示两台主机(A和B)的用户进程通过互联的通信子网进行通信的情况。图中两个传输层之间有一条双向箭头,表示传输层为应用进程之间提供的逻辑通信。所谓逻辑通信指应用进程的报文到达传输层后,似乎是直接沿着水平方向传送到远地的传输层,但事实上应用进程之间并没有一条水平方向的物理连接,被传送的数据实际上是经过传输层以下各层及通信子网来传送的。在通信子网互联时,由于各通信子网所提供的服务不一定相同,传输层的存在就弥补了各通信子网所提供服务的差异和不足,并在其提供的服务的基础上,利用传输层的协议及增加的服务功能,使得通信子网的用户得到一个面向通信的通用的传输接口。此时,各通信子网对两端用户进程则是透明的,而对高层用户而言,传输层则屏蔽了通信子网或网络群的具体细节,用户进程所看到的只是在两个传输层实体之间存在着一条端到端的可靠的通信链路。不难看出,传输层协议的复杂程度与通信子网提供的服务有关。通信子网提供的服务越多,传输层协议就越简单。反之,如通信子网所提供的服务越少,传输层协议就越复杂。从某种意义上来说,传输层协议填补了用户的要求与通信子网所提供的服务之间的差距。如前所述,网络层提供虚电路(面向连接的)和数据报(无连接的)两种服务,对于提供虚电路服务者,如果用户怀疑通信子网提供的虚电路服务的可靠性,此时传输层还必须具有端到端的差错控制和流量控制的功能。而对于提供数据报服务者,传输层既要负责报文无差错、不丢失、不重复,而且还要保证报文的顺序性,此时的传输层协议就要比前者复杂得多。从某种意义上来讲,传输层协议与数据链路层协议相类似,它们都要解决差错控制、流量控制和排序等问题,但其间的明显差异是它们所处的环境不同。数据链路层的环境是两个分组交换结点(PSN)直接相连的一条物理信道,而传输层的环境是两个主机之间的通信子网。由于传输层的环境要比数据链路层的环境复杂,从而对传输层协议的复杂程度产生很大的影响。这些影响主要体现在以下几个方面:第一,传输层建立传输连接的过程较复杂,需要有明确的路由选择才能通过通信子网找到目的主机中的用户进程;第二,由于通信子网的交换结点具有存储能力,分组在各交换结点上被存储转发,这就要求传输层协议适当处理因存储转发而出现的各种问题;第三,因通信子网可能同时存在多条链路,其连接数目又是动态变化的,传输层协议应采用不同的管理方法;第四,传输层必须给出目的地址,而数据链路层却不用给出目的地址。总之,传输层协议比数据链路层协议更复杂。设计传输层的目的是弥补通信子网服务的不足,提高传输服务的可靠性与保证服务质量(QOS)。传输层是计算机网络体系结构中非常重要的一层。传输层的作用是在源主机与目的主机进程之间提供端到端数据传输,而传输层以下各层只提供相邻结点之间的点对点数据传输,如源主机-路由器、路由器-路由器、路由器-目的主机的数据传输。从“点对点”通信到“端到端”通信是一次质的飞跃,传输层为此需要引入许多新的概念和新的机制。6.1.2传输层向上层提供的服务传输层是第一个端对端的层次。有了传输层后,高层用户就可利用传输层的服务直接进行端到端的数据传输,从而不必知道通信子网的存在,通过传输层的屏蔽,高层用户看不到通信子网的更替和技术变化,网络中通信子网是指网络层及其以下的部分。传输层在网络分层结构中起着承上启下的作用,它使用了网络层提供的服务,并通过执行传输层协议,针对高层屏蔽通信子网在技术、设计上的差异和服务质量的不足,向高层提供一个标准的、完善的通信服务。通常,在高层用户请求建立一条传输通信连接时,传输层就通过网络层在通信子网中建立一条独立的网络连接。若需要较高的吞吐量,传输层也可以建立多条网络连接来支持一条传输连接,这就是分流(splitting)。或者,为了节省费用,传输层也可以让多个传输通信合用一条网络连接,称为复用(multiplexing)。传输层还要处理端到端的差错控制和流量控制问题。概括地说,传输层为上层用户提供端对端的透明优化数据传输服务。在传输层设计中,有两种可能的方法。第一种方法是针对每一种通信子网和所需要的传输服务都设计一个传输层协议。这种方式的好处在于可以有的放矢地解决问题,协议简捷,没有更多额外开销,效率很高,但协议缺乏通用性。第二种方法是针对通信子网可能的服务类型和各种传输服务需求,设计一个通用的传输层协议。这种标准化的设计思想可能把传输层协议变得大而全,效率低。一种折衷的方案是将通信子网分类,针对每一类通信子网设计相应的传输层协议,既保证效率又不失通用性。从通信和信息处理的角度看,应用层是面向信息处理的,而传输层是为应用层提供通信服务的。传输层是属于网络中提供通信服务的最高层。有了传输层后,应用层的网络应用程序不必担心不同的子网接口和不可靠的数据传输。传输层可以起到隔离通信子网的技术差异性,如网络拓扑、通信协议的差异,改善传输可靠性的作用。因此,传输层是为用户提供可靠的数据传输服务的关键层。传输层的最终目标是向它的用户,也就是应用层中的进程提供高效,可靠和经济的服务,为了实现这一目标,在传输层使用网络层提供的服务,同时通过传输协议完成传输层地功能,完成传输层功能的硬件和软件被称为传输实体(transportentity),传输实体可能位于操作系统的内核,或者在一个独立的用户进程中,或者以一个链接库的形式被绑定到网络应用中,或者位于网络接口卡上,网络层,传输层和应用层之间的关系如图6-2所示:如同网络层有两种不同类型的服务(面向连接的和无连接的)一样,传输服务的类型也有两种。其中面向连接的传输服务是一种可靠的服务,整个连接有三个阶段:建立连接、数据传输和释放连接,这在许多方面与面向连接的网络服务类似。另外,无连接的传输服务与无连接的网络服务也非常相似。在协议栈中,传输层位于网络层之上。传输层协议为不同主机上运行的进程提供逻辑通信,而网络层协议则为不同主机提供逻辑通信。这个区别非常重要。在一个终端系统中,传输层协议将应用进程的消息传送到网络边缘(也就是网络层),反之亦然;但是它并不涉及消息是如何在网络层之间传送的工作。事实上,中间路由器对于传输层加在应用程序消息上的信息不能做任何识别和处理。传输层协议所提供的服务通常受限于位于其下方的网络层协议。如果网络层协议不能提供主机之间传送的TPDU(传输协议数据单元)的延迟和带宽保证,那么传输层协议也不可能提供进程之间传送的消息的延迟和带宽保证。传输层的代码完全运行在用户的机器上,但是网络层主要运行在由承运商控制的路由器上(至少对于广域网是如此)。如果网络层提供的服务不够用,那会怎么样呢?如果它频繁地丢失分组该怎么办?如果路由器时常崩溃又该怎么办呢?用户在网络层上并没有真正的控制权,也就是用户不能对通信子网加以控制,因而无法采用更优的通信处理机制来解决网络层服务质量太差的问题,更不能通过改进数据链路层纠错能力来改善它,惟一的可能是在网络层之上的另一层中提高服务质量。如果在一个面向连接的子网中,一个传输实体在执行一个长时间的传输过程时,突然接到通知说它的网络层连接已经被意外终止了,而且也不知道当前正在传输的那些数据到底怎么样,那么,该传输实体可以与远程的传输实体建立起新的网络层连接。利用新建立的连接,它可以向对方发送一个查询请求,询问哪些数据已经到达,哪些数据还没有到达,然后从中断的地方开始继续向对方发送数据。TPDU用户网络实体传输实体用户网络实体传输实体传输地址网络地址传输协议应用∕传输层接口传输∕网络层接口图6-2网络层、传输层和应用层之间的关系从本质来讲,由于传输层的存在,这使得传输服务有可能比网络服务更加可靠。丢失的分组和损坏的数据可以在传输层上检测出来,并且由传输层来补偿。由于有了传输层,应用开发人员可以根据一组标准的原语来编写代码,而且他们的程序有可能运行在各种各样的网络上,他们不用处理不同的子网接口。也不用担心不可靠的传输过程。传输层承担了将子网的技术、设计和各种缺陷与上层隔离的关键作用。并且即使当下面的网络层协议使得网络层并不能提供某些相应的服务时,传输层协议仍然可以提供某些特定服务。6.1.3传输服务原语通常,传输实体也称为传输服务提供者,而使用传输服务的用户(可能是会话实体,也可能是应用实体)称为传输服务用户,简称TS用户。为了让TS用户访问传输服务,传输层必须为TS用户提供一些操作,也就是说,提供一个传输服务接口,每个传输服务都有它自己的接口。这就是传输服务原语。表6-1给出了抽象的传输服务原语。表6-1抽象的传输服务原语阶段服务原语参数连接建立建立连接T—Contact.Req被呼地址,主呼地址,选项,服务质量,TS用户数据T—Connect.Ind被呼地址,主呼地址,选项,服务质量,TS用户数据T—Connect.Rsp响应地址,选项,服务质量,Ts用户数据T—Connect.Cnf响应地址,选项,服务质量,TS用户数据数据传输常规数据T—Data.ReqTS用户数据T—Data.IndTS用户数据加速数据T—Expedited—Data.ReqTS用户数据T—Expedited—Data.IndTS用户数据连接释放释放连接T—Disconnect.ReqTS用户数据T—Disconnect.Ind连接释放原因,TS用户数据传输层通过传输服务原语向传输用户提供服务,取决于不同的系统,传输服务原语的表现(实现)形式可以有所不同,在Unix环境下通过Socket形式来实现,在Windows环境下一般都通过Winsock来实现。20世纪80年代初,美国高级(远景)研究计划署(ARPA)给伯克利的加利福尼亚大学提供了资金,让他们在UNIX操作系统下实现TCP/IP协议。在这个项目中,一组伯克利研究人员为TCP/IP网络通信开发了一个API。设计人员将这个API称为Socket接口,Socket接口是TCP/IP网络的API。也就是说,Socket接口规定了许多函数和例程,程序员可以用它们来开发TCP/IP网络上的应用程序。今天,Socket接口是TCP/IP网络最为通用的API之一。WindowsSockets(WinSock)是一个基于Socket模型的API。WindowsAPI只在MicrosoftWindows操作系统类中使用。WinSock是以动态链接库(DLL)来实现Socket接口的。6.1.4传输服务应用举例本小节我们介绍一个UNIX下的Socket编程例子来说明传输服务应用。一个非常简单的Internet文件服务器和一个与该服务器配合使用的例子客户,要理解这个例子,我们需要对Socket编程有一定的认识。1.Socket处理过程网络通信包括两台主机或两个进程,通过网络传递它们之间的数据。网络专家将网络会话的每一端称为一个端点。当使用Socket接口对网络通信编程时,Socket是网络通信过程中端点的抽象表示。为了进行网络通信(通过Socket接口),程序在网络会话的每端都需要一个Socket。两个Socket之间的通信可以是面向连接的(点对点连接),也可以是无连接的。Socket接口使用“打开--读/写--关闭”这样的处理过程。为了实现TCP/IP通信,程序首先打开一个到网络的连接。接着,程序可以通过这个连接读和写数据。最后,程序必须关闭这个连接。许多网络调用都需要一个变元,该变元是指向Socket地址结构的指针,在中定义。structsockaddr{u_shortsa_family;/addressfamily:AF—XXXvalue/charsa_data[14];/upto14bytesofprotocol_specificaddress/}其中skdata是按照地址的类型进行解释的,对于Internet协议集,在中:structin_addr{u_longs_addr;/32bitnetid/hostid.networkbyteordered/};structsockaddr_in{shortsin_family;/AF_INET/u_shortsin_port;/16bitportnumber,networkbyteordered/structin_addrsin_addr;/32bitnetid/hostid.networkbyteordered/charsin_zero[8];/unused/}一般说来,若使用TCP/IP协议,应用程序在调用SocketAPI时可以直接使用structsockaddr_in结构,它实际上等同于sockaddr。⑴建立一个Socket为了进行网络I/O,第一件事就是调用Socket函数,指定所要求的协议类型(TCP/UDP/IP等)。Socket函数返回一个类似文件描述符的句柄:Socket_handler=socket(intfamily,inttype,intprotocol);其中,family可以选AF_UNIX(UNIXsocket)、AF_INET(Internet)等。Socket接口使用符号常量SOCK_DGRAM表示数据报,用SOCK_STREAM表示字节流。Socket接口还定义了叫做rawsocket(原始Socket)(SOCK_RAW)的第三种通信类型。rawsocket让程序使用网络自己的低层协议。对于TCP/IP网络,协议的符号常数是以前缀IPPROTO_开始的。例如,IPPROTO_TCP和IPPROTO_UDP分别表示TCP和UDP协议。调用Socket函数时,Socket执行体将建立一个Socket,并返回一个指向描述符表入口的Socket句柄(或描述符)。Socket执行体为你管理描述符表。访问描述符表的唯一途径是通过Socket描述符。通信完成之后,用户应该通过调用close函数来关闭Socket,释放所分配的资源:Result=close(intsock_handle)。⑵配置Socket面向连接的客户程序使用connect函数来配置Socket。connect函数要求你指定一个Socket句柄、一个包含远地主机信息的地址结构和此地址结构的长度:Result=connect(intsocket_handle,structsockaddrservaddr,intaddrlen);connect函数的第一个参数,即Socket句柄,是Socket函数返回的Socket描述符。第二个参数,即远地Socket地址,是一个指向特定Socket地址结构的指针,其内容取决于程序使用的协议族。第三个参数,即地址长度,简单地告诉Socket执行体远地Socket地址结构(第二个参数)的字节数。由于无连接客户程序没有和远地主机建立直接连接,所以它必须对协议端口进行侦听,以便接收对它的服务请求所产生的数据报应答。同样,为了接收客户的请求,服务器程序必须对一个特定的协议端口进行侦听。SocketAPI中的bind函数让程序将一个本地地址(包括主机地址和协议端口)和一个Socket联系起来:Result=bind(intsocket_handle,streetsockaddrmyaddr,intaddden)⑶通过Socket传输数据①通过一个连接的Socket发送数据使用面向连接的SocketAPI函数不需要目的地址当作其参数。send,write和writev函数只和连接的Socket一起工作,它们要求指明一个Socket句柄作为第一个参数,例如:Result=write(intsocket_handle,chatmessage_buffer,intbuffer_length);write的第二个参数指向一个包含传输信息的数据缓冲区;第三个参数简单地指明缓冲区的大小,和UNIX下普通的文件IO类似。Result=writev(intsocket_handle,structiovecio_vector[],intiovcount);structiovec{caddr_tiov_base;/startingaddressofbuffer/Intiov_len;/sizeofbufferinbytes/}writev的第二个参数指明一个包含一列指针的数组的地址。当writev函数传输数据时,它将发送由指针数组指定的每一内存单元内包含的数据。writev的第三个参数指明数组的大小。writev提供了标准系统调用write的变形,可以写入不连续的缓存。Result=send(intsocket_handle,charbuffer,intbufflen,intspecial_flags);send函数可以通过可选标志special_flags对传输进行控制,它或者为0或者为下面两种常数的“或”:MSG_OOB(接收加急数据)、MSG_DONTROUTE(旁路路由选择)。例如,你可以使用一个标志MSG_OOB,告诉接收进程你在传送带外(outofband)数据,它将具有比其他数据更高的优先级。这三个函数都返回一个整数值:如果正确执行,函数将返回传送的字节数;如果发生错误,函数返回-l。②通过一个无连接的Socket发送数据为了通过一个无连接的Socket发送数据,可以使用sendto和sendmsg这两个SocketAPI函数。sendto函数要求六个参数,其前四个参数和send函数相同,它的第五个参数确定目的地址,第六个参数指明目的地址的大小(以字节为单位):Result=sendto(intsocket_handle,charbuffer,intbuflen,intflags,structsockaddrto,intaddrlen);sendmsg函数传输数据时,让你使用一个报文结构而不是一个简单的数据缓冲区:Result=sendmsg(intsocket_handle,structmsghdrms9,intspecial—flus);structrnsghdr{caddr_tmsg_name;/optionaladdressintmsg_namelen;/sizeofaddressstruetiovecmsg_iov;/scatter/gatherarrayintmsg_iovlen;/elementsinmsg_iovcaddr_tmsg_accrights;/acceflsrightssent/received/intmsg_accrightslen;};其中,msg_iov为一个指针数组,指针数组所指向的每一数据块中的数据都将被发送,其数据结构见上文。special_flags和前面send函数中相应参数的意义一样。③通过Socket接收数据Socket接口包括五个与发送数据函数相对应的接收函数(read,ready,recv,recvfrom,recvmsg)。使用类似的参数。Result=read(intsock_handle,chatbuffer,intlength)Result=readv(intsock_handle,streetioveciov[],intiovcount)Result=recv(intsock_handh,charbuf,intlen,intflags)Result=recvfrom(intsock_handle,charbuf,intlen,structsockaddrfromaddr,intfromlen)Result=recvmsg(intsock_handle,structmsghdrmsg,intflags)read中的buffer和length参数分别给出缓冲区地址以及缓冲区长度,收到的数据将放在缓冲区中。返回值给出了所接收的字节数,如果出错,则返回-1。readv中的iov字段和iovcount一起指出了一些离散的缓冲区位置,这些缓冲区可以不是连续的,收到的数据将放在缓冲区中。返回值给出了所接收的字节数,如果出错,则返回-1。recv中的buf和len指出了所使用的缓冲区;flags字段和前面send中的类似,用户通过设置这个字段来选择是否接收紧急数据(MSG_OOB),是否只看看队列中的数据而不把数据从队列中清除,这样下次从该socket接收数据时仍然接收到同样的数据(MSG_PEEK)。recvfrom中的buf和len指出了所使用的缓冲区;fromaddr用来保存所接收的消息发送者的地址,fromlen指出该地址的长度。返回值给出了所接收的字节数,如果出错,则返回-1。recvmsg中的msg指出了所使用的缓冲区,相应的数据结构在描述sendmsg时给出;flag和前面recv中描述的一致。返回值给出了所接收的字节数,如果出错,则返回-l。⑷服务器的Socket使用面向连接的服务器需要调用listen和accept函数。listen函数先将服务器置于被动的侦听模式,accept函数接着建立一个Socket连接。listen函数将所有到达的服务请求在一个请求队列上排队,也就是说,listen函数让Socket执行体建立一个输入数据队列,将到达的服务请求保存在此队列上,直到程序处理它们为止。listen函数需要两个参数:Socket句柄和队列长度:ResuIt=listen(intSocket_handle.intquery_length);accept函数让服务器接收客户的连接请求。在建立好输入队列以后,服务器就调用accept函数,然后睡眠,并等待客户的连接请求。accept函数需要三个参数:Socket句柄,Socket地址和地址长度。当请求到达一个特定的Socket时,Socket执行体就把请求连接的客户地址填入第二个参数指向的Socket地址结构中。Result=accept(intSocket_handle,structsockaddraddr,intlength);当accept函数监视的Socket收到连接请求时,Socket执行体将建立一个新的Socket。执行体将这个新Socket和请求连接进程的地址联系起来。收到服务请求的初始Socket仍具有任意的网络地址,因此它可继续接收进来的服务请求。⑸Socket编程大致流程下面的程序显示了使用面向连接协议时典型的Socket系统调用。服务器程序建立一个Socket,并调用bind函数将此Socket和本地协议端口联系起来,然后用listen和accept函数将此Socket函数置于被动的侦听模式并接收和建立连接。客户程序也建立一个Socket,接着调用connect函数启动网络对话。在客户和服务器建立连接以后,就可以用read、write等函数进行通信了。2.Socket程序设计实例//一个Internet文件服务器/Theserverrespondsbysendingthewholefile./#include/Thisistheservercode/#include#include#include#include#defineSERVER_PORTl2345/arbitrary.butclient&servermustagree/#defineBUF_SIZE4096/blocktransfersize/#defineQUEUE_SIZEl0intmain(intargc,charargv[]){ints,b,I,fd,sa,bytes,on=1;charbuf[BUF_SIZE];/bufferforoutgoingfile/structsockaddr_inchannel;/holdsIPaddress//Buildaddressstructuretobindtosocket./memset(&channel,0,sizeof(channel));/zerochannel/channel.sin_family=AF_INET;channel.sin_addr.s—addr=htonI(INADDR_ANY);channel.sin—port=htons(SERVER_PORT);/Passiveopen.Waitforconnection./s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);/createsocket/if(S<0)fatal(“socketfailed”);setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char)&on,sizeof(on));b=bind(s,(structsockaddr)&channel,sjzeof(channel));if(b<0)fatal(“bindfailed”);I=listen(s,QUEUE_SIZE);/specifyqueuesize/if(1<0)fatal(“listenfailed”);/Socketisnowsetupandbound.Waitforconnectionandprocessit./while(1){sa=accept(s,0,0);/blockforconnectionrequest/if(sa<0)fatal(”acceptfailed“);read(sa,buf,BUF_SIZE);/readfilenamefromsocket//Getandreturnthefile.fd=open(buf,O_RDONLY);/openthetlietobesentback/if(fd<0)fatal(“openfailed“);while(1){bytes=read(fd,buf,BUF_SIZE);/readromfile/if(bytes<=0)break;/checkforendoffile/write(sa,buf,bytes);/writebytestosocket/}close(fd);/closefile/close(sa);/closeconnection/}}/Thispagecontainsaclientprogramthatcanrequestafilefromtheserverprogram/#include#include#include#include#defineSERVER_PORTl2345/arbitrary,butclient&servermustagree/#defineBUF_SIZE4096/blocktransfersize/intmain(intargc,charargv){intc,s,bytes;charbuf[BUF_SIZE];/bufferforincomingfile/structhostenth;/infoaboutserver/structsockaddr_inchannel;/holdsIPaddress/if(argc!=3)fatal(“Usage:clientserver-namefile-name”);h=gethoslbyname(argv[1]):/lookuphost’sIPaddress/if(!h)fatal(“gethostbynamefailed”);s=socket(PF_INET,SOCK_STREAM,IPPROT0_TCP);if(S<0)fatal(“socket”);memset(&channel,0,sizeof(channel));channel.sin_family=AF_INET;memcpy(&channel.sin_addr.s_addr,h->h_addr,h->h_length);channel.sin_port=htons(SERVER_PORT);c=connect(s,(structsockaddr)&channel,sizeof(channel));if(C<0)fatal(“connectfailed”);/Connectionisnowestablished.Sendfilenameincluding0byteatend./write(s,argv[2],strlen(argv[2])+1);/Gogetfhefileandwriteittostandardoutput./while(1){bytes=read(s,buf,BUF_SIZE);/readfromsocket/if(bytes<=0)exit(O);/checkforendoffile/write(1,buf,bytes);/writetostandardoutput/}}fatal(charstring){printf(“%s\\n”,string);exit(1);}说明一下,本实例中的服务器程序并不完善,没有涉及安全性,并且使用了UNIX的系统调用,所以它不是平台无关的,同时也作了某些技术上不合理的假设,比如假设文件名一定适合缓冲区(即不会超出缓冲区的大小),并旦可以以原子方式传送出去。由于它按照严格的顺序关系来处理所有的请求(因为它只有一个线程)所以它的性能很差。尽管存在这些缺点,但它确实是一个完整的、可以工作的Internet文件服务器。6.2传输协议的要素传输协议是传输层的核心,两个传输实体之间交换的信息是传输协议的一个重要部分,这种信息被称为传输协议数据单元TPDU(Transport-LayerProtocolDataUnit)。为了说明问题,我们假定所使用的TPDU如表6-2所示。表6-2传输协议的TPDUTPDU含义CR传输连接请求,要求与对等传输实体建立传输连接CC确认,对CRTPDU的确认DR释放请求,要求释放与对等传输实体之间的传输连接DC确认,对DRTPDU的确认DT数据,一个传输实体向对等传输实体发送用户数据AK确认,对数据TPDU的认可REJECT拒绝,对数据TPDU拒绝接受在实际的传输协议中,具体的TPDU可能和上述表格的TPDU有所不同,一般不同传输协议的TPDU定义也有所不同。对于传输层而言,服务质量(QoS)是十分重要的概念。传输服务质量衡量了传输层的总体性能,传输层要求弥补网络层服务质量的缺陷:如果网络层服务质量比较高,那么传输层可以实现得比较简单;如果网络层服务质量比较低,那么要求传输层实现比较复杂的功能,这样才能使传输层的服务质量达到一定的高度那么,传输层服务质量如何衡量呢?可以使用某些可数值化的参数来表达传输层服务质量:⑴连接建立延迟:连接建立延迟是指从传输服务用户要求建立连接,到收到连接确认之间所经历的时间。它包括了远端传输实体的处理延迟。与所有衡量延迟的参数一样,延迟越短,服务质量越好。⑵连接建立失败的概率:连接建立失败的概率是指在最大连接建立延迟时间内,连接未能建立的可能性。例如,由于网络拥塞、缺少缓冲区或其他原因造成的连接建立失败。⑶吞吐率:吞吐率是指每秒钟传输的用户数据的字节数,它是在某个时间间隔内测量得到的数据。同一条路径的不同传输方向的吞吐率可以是不同的。每个传输方向需要分别用各自的吞吐率来衡量。⑷传输延迟:传输延迟是指从源主机开始传输用户发送报文,到目的主机传输用户接收到报文为止所经历的时间。与吞吐率一样,同一条路径的不同传输方向的传输延迟可以是不同的。每个传输方向需要分别用各自的传输延迟来衡量。⑸残余误码率:残余误码率是指传输连接上错误的数据传输量占全部传输的数据量的比例,理论上说,这个比例应该为0,因为传输层的主要功能之一就是要提供可靠服务,但实际上这是做不到的。⑹安全保护:安全保护为传输用户提供了传输层的保护,以防止未经授权的第三方读取或修改。⑺优先级:优先级为传输用户提供了一种用以表明哪些连接更为重要的方法。当发生拥塞事件时,确保高优先级的连接比低优先级的连接先获得服务。⑻恢复功能:恢复功能给出了当出现内部问题或拥塞情况下,传输层本身自发终止连接的可能性。网络中的N层总是要向N+1层提供比N—1层更完善、更高质量的服务,否则N层也就没有必要存在了,传输层的协议设计也是遵循这一基本的指导思想,我们在传输协议中要讨论的内容主要有:编址、连接管理、流量控制和缓冲、多路复用和崩溃恢复。6.2.1编址当一个传输层的用户(可能是会话实体,也可能是其他应用进程)希望与另一个用户建立连接的时候,它必须说明与那一个具体的远程用户相连。通常使用的方法是为那些能够监听连接请求的进程定义相应的传输地址。常用的方式是定义传输服务访问点(TSAP:TransportServiceAccessPoint),在Internet上,采用称为端口号(port)的方法。IP地址和端口号两者结合相当于一个TSAP,它唯一标识了一个应用进程。同样地,网络层上类似的端点(即网络层地址)称为网络服务执行点(NSAP:NetworkServiceAccessPoint),IP地址是它的特例。如图6-3所示,它描述了TSAP、NASP和传输连接之间的关系。假设机器B上有一个时间服务进程向全网提供服务,机器A上的进程若要查询当前时间,可能会有如下动作:机器B上的时间服务进程在众所周知的端口(TSAPb)等待传输连接请求。传输实体传输实体传输层用户传输层用户网络层实体及下层实体网络层实体及下层实体网络传输协议TPDUNSAPTSAPAB图6-3传输协议寻址方法机器A上的应用进程向机器B的端口(TSAPb)发出传输连接请求,指明自己的端口和网络地址(假设为TSAPa),表示机器A的应用进程与机器B的时间服务进程建立传输连接。上述连接请求是传输实体根据内部情况和有关地址,按照传输协议,通过网络层提供的功能来传递的。如果连到TSAPb端口的时间服务进程同意的话,就向机器B确认连接。机器A传输实体向其应用进程发出连接证实,表示传输连接已经建立成功。机器A的应用进程在这条传输连接上发出询问时间的请求。机器B的时间进程在传输连接上传递时间信息。机器A的应用进程在收到时间信息后释放传输连接。6.2.2连接管理由于传输层协议的复杂程度与通信子网提供的服务有关,而通信用户又必须面对不同通信网络进行数据传输的事实,这就需要研究针对不同通信网络的服务质量进行数据传输的传输层协议。下面以0SI网络服务和传输协议为例,来说明传输协议的分类情况。ISO定义了3种类型的网络服务质量,它们是:A型网络服务—有可接受的残余差错率和可接受的故障通知率的网络连接;B型网络服务—有可接受的残余差错率和不可接受的故障通知率的网络连接;C型网络服务—有不可接受的残余差错率和不可接受的故障通知率的网络连接。在这3种类型中,A型网络服务是一种最完善的服务,服务质量最高,分组的错序、重复和丢失的情况均可忽略不计,因此基于A型服务的传输协议非常简单。目前提供A型服务的公用广域网几乎没有,但一些局域网提供的服务相当接近A型网络服务。B型网络服务质量居次,残留差错是指未纠正的而且是网络服务提供者没有检测到的差错,被告知的故障是指网络层检测到的并通知传输实体予以纠正的故障。因此B型网络服务仅要求传输协议具有差错恢复功能,提供虚电路服务的广域网和多数X.25公用分组交换网均属此类。C型网络服务相当不可靠,质量最差。即使发生了数据丢失、重复、失序或被篡改等事件,这种网络也不可能检测到差错,因此驻留在C型网络服务的传输协议必须具有检测网络差错的能力和差错恢复的功能。提供数据报服务的广域网、分组无线电网和很多互联网均属于这一类,此时的传输协议是最为复杂的。ISO经过多年研究和讨论,于1984年通过了0SI传输协议的标准(即ISO8072和ISO8073)。基于3种类型的网络服务,ISO定义了面向连接的5种类型的传输协议,即0类~4类传输协议。这5种类型传输协议的主要特点如下。0类(简单类)此类传输协议提供最简单的协议机制,以支持A型网络。其功能是建立一个简单的端到端的传输连接,要求并假定网络连接不会出错,依靠下面网络层对数据的正确传送,传输协议不再进行排序和流控。它只提供建立和释放连接的机制。1类(基本差错恢复类)此类传输协议也较简单,提供最少服务的连接,具有基本的差错恢复功能。基本差错是指出现网络连接断开或网络连接失败,或者收到一个未被认可的传输连接的数据单元。2类(多路复用类)此类传输协议也是为使用可靠的网络(A型)而设计的。它基本上是对0类传输协议的增强,具有多路复用功能,即允许多个传输连接共享同一个网络连接,但不具备恢复网络连接故障的功能。为了达到复用的目的,此类协议应具有相应的流量控制功能。它与0类不同的是,在其协议中允许两个或多个传输连接向同一个网络连接发送数据。当存在多个传输连接时,每个连接的流量都非常小,所以可以把多个传输连接复用到一条网络连接上,以减少网络开销。3类(差错恢复和多路复用类)此类传输协议基本上是l类和2类的组合。它既具有多路复用功能,又具有差错恢复功能。4类(差错检测与恢复类)此类传输协议是针对C型网络服务而设计的。它可以在网络服务质量很差的情况下,进行高可靠性的数据传输,并具有差错检测与恢复,以及多路复用等功能。表6-3归纳了上述3种网络服务类型和5种类型传输协议之间的关系。表6-30SI传输协议的分类传输协议类别面向的网络服务类型基本功能0类A简单的端到端连接1类B基本差错恢复2类A多路复用3类B差错恢复与多路复用4类C差错检测与恢复,多路复用从上面可以看出,对于面向连接的服务,即使是可靠的网络服务,还是需要连接的建立和释放过程。连接管理就是使连接的建立和释放能正常地进行。建立连接时要解决以下三个问题。⑴使每一端能够确知另一端是否存在。⑵进行选项协商(如协议类、最大窗口大小、服务质量等)。⑶对传输实体资源(如缓冲区、连接表的表项等)进行分配。图6-4示出了连接建立的全过程,其操作步骤如下:⑴传输实体A向传输实体B发出连接请求报文CRTPDU,CRTPDU中包括发送序号;⑵传输实体B收到连接请求报文后,如同意连接,则回答确认报文CCTPDU,CCTPDU中包括发送序号和对CR中序号的确认;⑶传输实体A收到确认报文后还要向传输实体B回答确认,以第一个DTTPDU作为对CCTPDU的确认。此时,运行客户进程的传输实体A向上层应用进程告知连接已建立。而运行服务器进程的传输实体B收到A的确认后,也通知上层应用进程,连接已经建立。以上连接建立的过程,通常称为三次握手(three-wayhandshake)。这个方法是Tomlinson(1975)引入的,那么,为什么建立连接时需要发送第三个报文段(即第三次握手)呢?其实,这个问题只要回答如果仅发送前两个报文(即二次握手),会出现什么问题就可以了。正如我们前面提到的C型网络服务,建立连接必须考虑到网络服务的不可靠性。在初始交换CRTPDU的连接建立过程(这个过程有时称为二次握手)中,假设A向B发出CRTPDU,它希望B返回CCTPDU以证实这条连接。此时可能出现两种错误:一种是A的CRTPDU丢失,另一种是B的应答CCTPDU丢失。这两种情况都可以通过重传CR/CCTPDU计时器来处理。这样,在A已发过一个CRTPDU之后,如果重传CRTPDU计时器超时,它就会重发一个CRTPDU。但是,这样处理可能会带来重复的CRTPDU。因为如是A最初的CRTPDU丢失了,当然不会产生两个CRTPDU。但如是B的响应丢失了,那么B可能会接收到两个来自A的CRTPDU。所有这些都意味着一旦连接建立,A和B都必须对重复的CR/CCTPDU加以处理。同样,一个延迟的数据报文段或丢失的确认也会带来重复的数据报文段。假设传输协议实体对每个新连接都是从序号l开始进行编号,如果来自旧连接的一个报文段在新连接建立之后,且合法的编号的数据报文段到达之前到达,这就造成旧的先到,新的后到的重复局面。对付这种情况的一种方法是扩大编号范围。采用三次握手可以防止上述现象的发生。因为A不向B的确认发确认,B因收不到确认,连接就无法建立起来。连接建立之后,就进人数据传输阶段。数据传输结束后,通信的任何一方都可以发出释放连接的请求,要求终止本次连接。如图6-5所示,其操作步骤如下(假设由A先发出连接释放请求):⑴传输实体A向传输实体B发出连接释放报文DRTPDU,DRTPDU包含最后发送的DTTPDU序号+1;⑵传输实体B收到释放连接报文后,如同意释放连接,则回答确认报文DCTPDU。DCTPDU包含DRTPDU中的序号;同时通知高层应用进程。这样,从A到B的连接就释放了,连接处于半关闭(half-close)状态。传输实体A传输实体BA发起一个连接B接受并确认A确认并开始传输CRTPDUCCTPDUDTTPDU图6-4连接建立过程此时,传输实体B不再接受传输实体A的数据,但B若有数据需要发往A,仍可继续发送。B向A的数据发送完毕后,B向A发出连接释放报文。⑶传输实体A收到连接释放报文后,必须对此做出确认,这样才将从B到A的反方向连接释放掉。传输实体A向上层应用进程告知整个连接已经全部释放。连接释放过程和连接建立时的三次握手本质上是一致的,传输实体同样要处理重复的和丢失的DR/DCTPDU,对于连接释放,也可使用三次握手方法以及计时器,传输实体A传输实体BA发起一个释放B接受并确认释放A到B的连接A接受并释放B到A的连接DRTPDUDCTPDU图6-5连接释放过程图6-6释放连接的4种情况主机1主机2主机1主机2(a)(b)DRDRACK发送DR并启动计时器释放连接发送ACK发送DR并启动计时器释放连接发送DR并启动计时器发送DR并启动计时器释放连接发送ACK丢失(超时)释放连接主机1主机2主机1主机2(c)(d)DRDRACK发送DR并启动计时器释放连接发送ACK发送DR并启动计时器释放连接发送DR并启动计时器发送DR并启动计时器(N次超时)释放连接丢失(超时)释放连接丢失DRDR(超时)发送DR并启动计时器发送DR并启动计时器丢失ACKDRDR(超时)发送DR并启动计时器DR如果使用三次握手方法,还需要一个ACKTPDU,如图6-6所示。在图6-6的(a)中,我们可以看到正常的情形,其中一个用户发送一个DRTPDU,以发起释放连接的过程。当它到达的时候,接收方也发送一个DRTPDU并启动一个定时器,该定时器的目的是为了防止它的DR丢失。当这个DR到达的时候,最初的发送方送回一个ACKTPDU,并且释放连接。最后,ACKTPDU到达的时候,接收方也释放连接。如果最后的ACKTPDU丢失的话,则如图6-6(b)所示,这种情形可以通过一个定时器来补救。当定时器超时的时候,不管怎么样,连接都被释放。现在考虑第二个DR被丢失的情形。发起释放连接操作的用户将接收不到期望的应答,所以它将超时,于是再次尝试释放连接。在图6-6(c)中,我们可以看到这个工作过程,图中假定第二次握手过程中没有TPDU丢失,所有的都被及时地递交给正确的接收方。在图6-6(d)所示的最后一个场景中,假设由于丢失TPDU的原因,因而所有重传DR的尝试也失败;除此以外,其他的情况与图6-6(c)中相同。经过N次重试之后,发送方放弃了,并且释放连接。同时,接收方超时,于是退出。6.2.3流量控制和缓冲在详细地讨论了连接的建立和释放过程以后,现在我们来看一看在使用连接的过程中如何对它们进行管理。其中一个关键问题我们前面已经看到过了:流控制。传输层中的流控制问题在有些方面与数据链路层中的情形相似,但是在另一些方面又有所不同。基本的相似之处是,在这两层上,都需要在每个连接上使用滑动窗口或者其他的方案以避免一个快速的发送方淹没掉一个慢速的接收方。主要的不同之处在于,一台路由器通常只有相对少量的线路,而一台主机可能有大量的连接。这一差异决定了在传输层上实现数据链路层的缓冲策略将是不切实际的。传输服务是通过建立连接的两个传输实体之间执行传输层协议来实现的。在某些方面,传输层协议和数据链路层协议很相似。它们都必须解决差错控制、分组拆装、流量控制等问题。通信的两个数据链路层之间是通过物理通道直接连接的。而两个会话主机的传输层之间面对的是一个通信子网。这个通信子网可能是一个结构十分复杂的互联网络。这一差异对协议的设计将会产生很大的影响。无论是主机-路由器,或者是路由器-路由器之间的数据链路连接,它们都是建立在一个点对点物理线路的基础之上的。因此,在设计传输层协议和数据链路层协议所面对的情况是不相同的。这种差距表现在:⑴传输层连接建立过程比较复杂;⑵传输层之间数据包传输过程比较复杂。在路由器-路由器之间传输一帧数据时,该帧可以直接通过两个路由器的物理线路,从源路由器传输到目的路由器。帧的传输延迟是结点处理的时间与物理线路传输延迟之和。两个会话的传输层之间传输的数据包,在通过子网的过程中需要经过多个路由器和通信线路,造成影响传输层之间数据包传输延迟与差错的因素太多。因此,人们必须研究数据包通过子网的差错控制、分组拆装、流量控制等问题,寻找合适的方法,制定相应的协议。在数据链路层中,发送方必须将往外发的帧缓冲起来,因为以后可能要重传这些帧。如果子网提供的是数据报服务,那么发送端传输实体必须也要缓冲TPDU,理由相同。如果接收方知道发送方缓冲了所有的TPDU一直到它们被确认为止,那么,接收方可能会,也可能不会为特定的连接分配特定数量的缓冲区,这要看它怎么觉得合适。例如,接收方可能只维护一个缓冲区池,让所有的连接共享这同一个池。当一个TPDU进来的时候,接收方企图为它动态地分配一个新的缓冲区。如果分配成功了,则接受该TPDU;否则将它丢弃。由于发送方已经准备好要重传那些被子网丢失的TPDU,让接收方丢弃TPDU;并无损害,只不过浪费一些资源而已。发送方会一直尝试发送TPDU,直至接收到确认为止。简而言之,如果网络服务不是可靠的,那么,发送方必须将所有发送的TPDU缓冲起来,就好像数据链路层中的做法一样。然而,对于可靠的网络服务,其他的平衡策略也是有可能的。尤其是,如果发送方知道接收方总是有缓冲区空间的话,它就不需要保留自己发送出去的TPDU的副本。然而,如果接收方不能够保证每一个进来的TPDU都被接受的活,则发送方无论如何一定要提供缓冲能力。在后一种情况下,发送方不能信任网络层的确认,因为网络层的确认仅仅意味着该TPDU到达了,而不见得它已经被接受。即使接收方已经同意要缓冲TPDU,接下来还有缓冲区大小的问题。如果大多数TPDU的长度都差不多,则很自然的做法是将缓冲区组织成一个相等大小缓冲区的池,每个缓冲区容纳一个TPDU,如图6-7(a)所示。然而,如果TPDU长度的偏差范围很大,既可能是终端上输人的少量字符,也可能是文件传输过程中的上千个字符,那么,用固定长度的缓冲区池就有问题了。如果将缓冲区的大小设置成最大可能的TPDU长度,那么,当短的TPDU到来的时候就会浪费内存空间。如果将缓冲区的大小设置成比TPDU的最大长度还小的话,则长的TPDU就需要多个缓冲区,从而带来额外的复杂性。缓冲区大小问题的另一方法是使用可变大小的缓冲区,如图6-7(b)所示。这里的优点是更好的内存利用率,付出的代价是使缓冲区的管理更加复杂。第三种可能的方案是为每个连接使用一个大的循环缓冲区,如图6-7(c)所示。如果所有连接的负载都很重的话,则此系统也能够很好地利用内存;但如果有些连接的负载较轻,则系统的内存使用情况很差。在源端缓冲和目标端缓冲之间的最佳折衷取决于该连接所承载的流量的类型。对于低带宽的突发性流量,比如交互终端所产生的流量,最好两端都不用给它分配任何专用的缓冲区,而是根据需要动态地分配缓冲区。由于发送方无法确定接收方是否能够获得一个缓冲区,所以发送方必须保留TPDU的一份副本,直至它被确认为止。另一方面,对于文件传输和其他的高带宽流量,最好的做法是,接收方分配一批可容纳整个窗口TPDU的缓冲区,从而允许最大速度的数据流。因此,对于低带宽的突发流量,最好在发送方缓冲数据,面对于高带宽的平滑流量,最好在接收方缓冲数据。随着连接被打开和关闭,以及流量模式的变化,发送方和接收方需要动态地调整它们的缓冲区分配策略。因此,传输协议应该允许发送主机请求另一端的缓冲区空间。缓冲区可以被分配给每个连接,或者集体分配给两台主机之间当前正在运行的所有连接。或者换一种做法,由于接收方知道它的缓冲区情况(但是不知道流量的情况〉,所以它可以告诉发送方“我已经为你预留了X个缓冲区”如果打开的连接的数量应该增加的话,则为每个连接分配的缓冲区数有必要相应地减少,因此,协议应该提供这种协商能力。为了管理动态的缓冲区分配过程,较为通用和合理的做法是将缓冲过程与确认机制分离开。动态的缓冲区管理实际上意昧着一个可变大小的窗口。刚开始的时候,发送方根据它所了解到的需求情况,请求一定数量的缓冲区。然后,接收方根据它的能力分配尽可能多的缓冲区,每次当发送方传输一个TPDU的时候,它必须减小缓冲区分配数,当分配数到达0的时候停止发送。然后,接收方在反向流量中独立地捎带确认和缓冲区分配数。图6-7(a)链式的固定大小的缓冲区(b)链式的可变大小的缓冲区(c)每个连接使用一个大的循环缓冲区未用空间TPDU1TPDU2TPDU3TPDU4(a)(b)(c)图6-8显示了在一个4位序列号的数据报子网中动态窗口管理的一种可能做法。假设如图中所示,缓冲区分配信息被放在单独的TPDU中,而不是捎带在反向流量中被传送到另一端。初始时,A想要8个缓冲区,但是B只分配了4个。然后A发送3个TPDU;其中第3个TPDU丟失,在第6行,B确认已经接收到直至序列号1(含)的所有TPDU,从而允许A释放这些缓冲区;同时进一步通知A,允许发送3个从序列号1之后开始的TPDU(即TPDU2、3和4)。A知道它已经发送了TPDU2;所以它认为现在可以发送TPDU3和4,于是它接下去就这么做了。这时候它被阻塞住,它必须等待分配更多的缓冲区。然而,在阻塞过程中,因超时而导致的重传仍然可以进行(笫9行)因为它们使用的缓冲区已经被分配了。在第10行,B确认已经接收到直至(含)序列号4的所有TPDU,但是拒绝让A继续发送。下一个从B到A的TPDU表明B巳分配了另一个缓冲区,从而允许A继续发送。在数据报网络中,如果控制TPDU也可能丟失的话,则这种缓冲区分配方案有可能引发一些潜在的问题。请看第16行,B现在已经为A分配了更多的缓冲区,但是,这个指示缓冲区分配的TPDU丢失了。由于控制TPDU并没有序列号,也不超时,所以A现在死锁了。为了避免这种情况,每台主机应该定期地在毎个连接上发送一些包含确认和缓冲区状态的控制TPDU。采用这种方法,死锁迟早会被打破。到现在为止,我们一直暗含着假定发送方数据率的惟一限制因素是接收方可供图6-8动态缓冲区分配过程箭头显示了传输的方向.省略号(…)代表一个丢失的TPDU使用的缓冲区空间的数量。随着内存价格的不断下跌,我们有可能为主机配备足够的内存,从而使得缓冲区短缺不再成为一个问题,即使可能发生,也极为少见。当缓冲区空间不再限制最大数据流的时候,另一个瓶颈将会出现:子网的承载能力。如果邻接的路由器之间每秒钟至多交换x个分组,并且在一对主机之间有k条互不相交的路径,那么,不管每台主机有多少可用的缓冲区空间,它们每秒钟交换的TPDU不可能超过kx个。如果发送方费力地往前推进(即每秒钟发送超过kx个TPDU)的话,子网将阻塞,因为它不可能以超过TPDU进来的速度来递交这些TPDU。这里需要的是一种基于子网的承载容量而不是接收方缓冲容量的动态调节机制。很显然,发送方必须使用流控制机制,以避免发送方同一时刻有太多未被确认而悬着的TPDU。Beisnes(1975)建议使用一种滑动窗口流控制方案,在他的方案中,发送方动态地调整窗口的大小,以便与网络的承载容量相匹配。如果网络每秒钟能够处理c个TPDU;,并且处理周期时间(包括发送、传播、排队、接收方的处理过程以及确认的返回)为r,那么,发送方的窗口应该是cr。如果发送方使用这样大小的窗口,那么,它通常可以按流水线方式全速的运行。网络性能只要减小一点点就有可能导致发送方阻塞。为了定期地调整窗口的大小,发送方可以监视这两个参数(c和r),然后重新计箅期望的窗口大小。承载容量很容易确定,发送方只要计算在一段时间中被确认的TPDU的数量,然后除以这段时间的长度即可。在测量过程中,发送方应该尽可能快地发送TPDU,以确保限制确认速率的因素是网络的承载容量,而不是较低的输入率。一个从发送出去到被确认所需要的时间可以精确地測量出来,它可以是运行过程中所维护的一个平均数。由于可用于任何一个流的网络容量在不停地随时间而变化,所以,发送方也应该频繁地调整窗口的大小,以便跟上其承载容量的变化。Internet使用了一种类似的方案。6.2.4多路复用对于传输协议和传输服务用户来讲,传输协议实现复用功能:多个用户使用同一个传输协议,它们通过TSAP加以区分。对于网络服务而言,传输实体也实现复用(向上复用和向下复用):多条传输连接复用一条网络连接(向上复用、复用/解复用);另一方面,一条传输连接可以使用多条网络连接(向下复用、分流与合流)。向上复用(复用与解复用)的使用往往是出于费用上的考虑,一般而言网络服务收费以网络连接为标准,多条传输连接复用一条网络连接可以在满足吞吐量的情况下尽量减少费用。向下复用(分流与合流)的目的是为了提供对单一网络失效的恢复能力,以及提高吞吐量。一般来说,多条网络连接上的吞吐量大于一条网络连接上的吞吐量,当然,吞吐量也不是无限制的,若两个结点之间有一条物理链路相连,那么传输连接的吞吐量不会超过该链路的容量。6.2.5崩溃恢复如果主机和路由器都有可能崩溃,那么,如何从这些崩溃事件中恢复运行就成为一个问题。如果传输实体完全在主机内部,则从网络和路由器的崩溃中恢复的方案是非常简单的。如果网络层提供的是数据报服务,那么,传输实体总是在期望那些丢失了的TPDU,并且它们知道该如何处理这些被丟失的情形。如果网络层提供的是面向连接的服务,那么,由于虚电路丢失了,所以处理的办法是建立一条新的虚电路,然后询问远程的传输实体:哪些TPDU已经接收到了,哪些还没有接收到。之后再重传那些尚未接收到的TPDU。一个更加麻烦的问题是如何从主机的崩溃中恢复过来。尤其是,当服务器崩溃并且快速启动之后,客户可能期望还能够在原来的基础上继续工作。为了说明其中的困难程度,我们假设一台主机(客户〉正在使用一个简单的停-等协议,来给另一台主机(文件服务器)发送一个大文件。服务器上的传输层只是简单地将接收进来的TPDU逐个传递给传输用户。在传输到一半的时候服务器崩溃了。当服务器恢复运行以后,它的内部表又被重新初始化,所以,它不知道原来的传输过程已经进行到哪儿了。为了试图从原先的状态中恢复过来,服务器可能给所有其他的主机发送一个广播TPDU,宣告自己刚才崩溃了,请它的客户们告诉它关于所有已打开连接的状态信息。每个客户可能处于以下两种状态之一,有一个未完成的TPDU:S1;或者,没有未完成的TPDU:S0。根据这一状态信息,客户必须确定是否重传最近的TPDU。初看起来似乎很明显:当客户知道服务器崩溃的时侯,只有当客户有一个未确认的TPDU正在等待处理(即处于状态S1)时它才应该重传。然而,进一步探究这种做法便会发现其中的困难所在。例如,请考虑这样的情形:服务器的传输实体首先发送一个确认,然后当确认被送出以后,向应用进程执行一个写数据操作。将一个写到输出流中,以及发送一个确认,这是两件不可能同时完成的独立事件。如果在确认被发送出去之后,但是在写操作完成之前服务器崩溃了,那么客户将会接收到确认,所以当崩溃恢复之后广播消息到来的时候,它处于状态S0中。因此客户不会重传,从而不正确地认为TPDU已经到达服务器的应用进程中了。客户的这一决定将导致丟失一个TPDU。这时候你可能会这样想:“这个问题很容易解决,只要重新修改一下程序,让它先执行写操作再发送确认即可”。你可以再试一试。请想象一下,如果写操作巳经完成,但在发送确认之前服务器崩溃了,那么,客户将处于状态S1中,因此它会重传,从而导致在服务器应用进程的数据流中出现一个未被检测到的重复TPDU。不管如何正确地编写客户和服务器程序的代码,总是存在使协议无法正确地恢复运行的情形。服务器程序的实现方法可以有两种:先发送确认,或者先写数据。而客户程序可以有四种不问的实现方法:总是重传最后的TPDU、永远不重传最后的TPDU、仅当处于状态S0中时才重传,或者仅当处于状态S1中时才重传。两者结合起来有8种组合,但是正如我们将会看到的,对于每一种组合都存在一些使协议失败的事件。在服务器端可能有三种事件:发送一个确认(A)、将数据写到输出进程(W)和崩溃(C)。这三种事件可以有6种不同的发生顺序:AC(W)、AWC、C(AW)、C(WA)、WAC和WC(A),这里的括号表示A或者W不可能跟在C的后面〔即一旦崩溃之后,它就崩溃了,不可能再发生其他的事件〕。图6-9显示了客户和服务器策略的8种组合,以及每一种组合的有效事件序列。请注意,对于毎一种策略,总是存在某一个使协议失败的事件序列。例如,如果客户总是重传的话,则AWC事件将生成一个未检测到的重复TPDU,但是其他两个事件可以正确地工作。进一步精心地修改协议也没有用。即使在服务器试图写TPDU之前,客户与服务器再多交换几个TPDU,从而客户可以确切地知道接下来将要发生什么事情,但客户也没有办法知道崩溃动作恰好发生在写操作之前还是之后。结论是不可避免的:在没有同步事件的条件下,主机的崩溃和恢复对于上面的层来说不可能是透明的。按照更加一般的术语表达,这个结论可以重新叙述为:从N层的崩溃中恢复的过程只能由N+1层来完成,并且仅当N+1层保留了足够的状态信息时才有可能恢复。正如前面所提到的,只要连接的每一端记录了它当前的传输状态信息,传输层就能够从网络层的失败中恢复过来。这个问题使我们进入到另一层面的思考:所谓端到端的确认到底意味着什么。原则上,传输协议是端到端的,而不像下面的层那样是链式的。现在请考虑这样的情形:一个用户向一个远程数据库发出一些事务请求。假设远程传输实体的实现方式是先将TPDU传递给上一层,然后再确认。即使在这个例子中,用户机器上接收到一个确认并不一定意味着远程主机巳经有足够的运行时间来真正更新数据库了。图6-9客户和服务器策略的不同组合—个真正的端到端确认是指:一旦接收到这个确认就表明一项工作确实已经完成了,而没有接收到确认则表明这项工作尚未完成。在实践中,这样的端到端确认可能是无法实现的。Saltzer(1984)更详细的讨论了这一点。6.3Internet传输协议—UDPInternet传输层上有两个协议:UDP和TCP,用户数据报协议(UDP)是一种无连接的传输层协议,而传输控制协议(TCP)是一种面向连接的传输层协议,下面我们先来讨论用户数据报协议(UDP),后面讨论传输控制协议(TCP)。6.3.1UDP介绍假设我们使用一个空的传输层协议。那么在发送方,我们应该考虑直接将从应用程序进程得到的消息传递给网络层;在接收方,我们应该考虑将从网络层得到的消息直接传送给应用程序进程。但是在我们前面讨论的内容中,并不是使用空的传输层协议。至少,为了在网络层和正确的进程之间传递信息,传输层提供了多路复用/多路分解服务。在RFC768中定义的UDP,和空的传输层协议一样几乎没做什么工作。除了多路复用,多路分解和极少的错误检测之外,它没有在IP之上加入任何东西。事实上,如果应用程序开发者选择了UDP而不是TCP,那么这个应用程序几乎就是直接和IP进行对话。UDP直接从应用程序进程得到消息,为了多路复用/多路分解服务将源和目标端口号附加上,加入两个小的字段,并把得到的数据报传递给网络层。网络层将数据报封装到IP数据报里,并使用尽力服务方式将数据报传递给接收方主机。如果该数据报到达了接收方主机,UDP通过端口号和IP目标地址将数据报中的内容传送给正确的应用程序进程。需要注意的是,如果使用UDP,那么在传送数据报之前,发送方和接收方的传输层实体之问就不需要进行握手。正是由于这个原因,UDP被称为无连接的。1.UDP协议的特点⑴UDP是一个无连接协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去取来自应用程序的数据,并尽可能快地把它放到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。⑵由于传输数据不建立连接,因此也就不需要维护连接状态,包括收发状态等,因此一台服务机可同时向多个客户机传输相同的消息。⑶UDP数据报的头部信息很短,只有8个字节,相对于TCP每一个数据报的20个字节的头部信息,UDP数据报的头部的额外开销很小。⑷吞吐量不受拥挤控制算法的调节,只受应用软件生成数据的速率、传输带宽、源端和终端主机性能的限制。⑸UDP使用尽力交付,即不保证可靠交付,因此主机不需要维持复杂的链接状态表(这里面有许多参数)。⑹UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付给IP层。既不拆分,也不合并,而是保留这些报文的边界。因此,应用程序需要选择合适的报文大小。2.UDP协议的应用既然UDP是一种不可靠的网络协议,那么还有什么使用价值或必要呢?其实不然,在有些情况下UDP协议可能会变得非常有用。因为UDP具有TCP所望尘莫及的速度优势。虽然TCP协议中植入了各种安全保障功能,但是在实际执行的过程中会占用大量的系统开销,无疑使速度受到严重的影响。反观UDP由于排除了信息可靠传递机制,将安全和排序等功能移交给上层应用来完成,极大降低了执行时间,使速度得到了保证。UDP在现在的很多多媒体应用程序中也被普遍使用,如因特网电话、实时视频会议以及存储的音频和视频流,因为相对于可靠性来说,这些应用更加注重实际性能,所以为了获得更好的使用效果(例如,更高的画面帧刷新速率)往往可以牺牲一定的可靠性(例如,会面质量)。例如,ProgressiveNetworks公司开发的RealAudio软件,它是在因特网上把预先录制的或者现场音乐实时传送给客户机的一种软件,该软件使用的RealAudioaudio-on-demandprotocol协议就是运行在UDP之上的协议,大多数因特网电话软件产品也都运行在UDP之上。UDP是一个不可靠的协议,但它是分发信息的一个理想协议。例如,在屏幕上报告股票市场、在屏幕上显示航空信息等等。UDP也用在路由信息协议RIP(RoutingInformationProtocol)中修改路由表。在这些应用场合下,如果有一个消息丢失,在几秒之后另一个新的消息就会替换它。我们经常使用“ping”命令来测试两台主机之间TCP/IP通信是否正常,其实“ping”命令的原理就是向对方主机发送UDP数据包,然后对方主机确认收到数据包,如果数据包是否到达的消息及时反馈回来,那么网络就是通的。DNS也是一个使用UDP的应用层协议的例子。当一个主机上的DNS应用程序需要执行查询操作时,它创建一个DNS查询消息并且将该消息传送给UDP套接字,在不需要执行任何握手的情况下,UDP给该消息加上一个头部字段并将这样得到的数据段传送给网络层。网络层将该UDP传送过来的数据段封装到一个数据报中,并将该数据报传送给名称服务器。而后,发出查询命令的主机的DNS应用程序就开始等待查询结果。如果它得不到结果(可能是由于其下方的网络丢失了查询命令或者查询结果信息),它或者对另外一个名称服务器发送查询命令,或者报告调用应用进程没有得到应答。在这里我们要说明一下,DNS规范除了允许DNS运行于UDP上之外,还允许其运行于TCP之上。当然,事实上,DNS几乎总是运行于UDP之上的。3.UDP的数据报结构UDP的报文又称为UDP数据报结构,如图6-10中所示,在RFC768中进行了定义。应用程序数据占用了UDP数据报中的数据字段。例如,对于DNS,数据字段或者包含了查询消息或者包含了应答消息。对于流式音频应用程序,音频采样填充了数据字段。UDP头部仅仅有4个字段,每一个包括2字节。正如在前一节中讨论的,端口号使得目标主机可以将应用进程数据传送给目标上运行的正确进程(也就是多路分解的功能)。如果数据报中带入了错误,接收方主机会使用校验和执行错误校验。事实上,错误校验在附加在UDP数据段上的IP头部中也会进行。但是我们为了看到总体面貌将这个细节忽略。我们将在下面讨论校验和的计算。长度字段以字节为单位,指明了UDP数据报的长度(包括头部)。源端口号目的端口号长度校验和应用程序数据(消息)具体来说,UDP用户数据报的头部有固定的8B的报头,报头主要有以下域:⑴端口号域端口号域包括源端口号和目的端口号。端口号的长度为16位⑵长度字段长度字段长度也是16位,它定义了包括报头在内的用户数据报的总长度。因此用户教据报的总长度最大为65535B,最小长度是8B。如果长度字段是8B,那么说明该用户数据报只有报头,而没有数据。⑶校验和字段检验和字段长度是16位,它用于防止UDP数据报在传输过程中出错。4.UDP校验和UDP校验和是用于错误检测服务的。发送方UDP计算该数据段所有的16比特字的和的反码。你可能觉得奇怪为什么在很多链路层协议(包括流行的以太网协议)已经给出了错误检测的情况下,UDP还会在头部给出校验和。原因就是不能保证源端和目的端的所有链路都提供错误检测—其中一个链路可能使用了一个不提供错误检测的协议。因为IP被假设是运行在任何第二层协议上的,所以作为一个安全措施在传输层提供错误检测是非常有用的。尽管UDP提供了错误检测,却并不提供错误恢复功能。UDP的一些实现方法简单地抛弃了被破坏的数据段;而另外的一些则将被破坏的数据段加上警告信息一起传递给应用程序。以上就是我们关于UDP的讨论。下面我们很快就会看到,TCP为应用程序提供了可靠数据传输和其他很多UDP无法提供的服务。很自然,TCP比UDP要复杂得多。图6-10UDP数据报结构6.3.2远程过程调用RPC(RemoteProcedureCall,远程过程调用),也就是说,调用过程代码并不是在调用者本地运行,而是要实现调用者与被调用者二地之间的连接与通信。RPC的基本通信模型是基于客户机/服务器进程间相互通信模型的一种同步通信形式;它对客户机提供了远程服务的过程抽象,其底层消息传递操作对客户机是透明的。在RPC中,客户机即是请求服务的调用者(Caller),而服务器则是执行Client的请求而被调用的程序(Callee)。RPC是一种客户机/服务器形式的服务:一个客户机进程可以执行另一台计算机上的进程、向这个进程提供数据、获取这个进程运行的结果等等。1.RPC的基本操作RPC借用了函数调用的概念,并且RPC模型提供了网络编程的抽象。利用这一模型,可以采用与本地过程调用类似的思想与概念来进行进程间的通信。通常的调用是发生在同一台计算机的同一个进程内的不同过程或函数之间,而RPC的调用是发生在一台计算机的客户机进程和另一台计算机的服务器进程之间,这两台计算机通过网络相连。RPC的基本操作如图6-11所示。首先是建立RPC服务,约定底层的RPC传输通道(UDP或是TCP)。客户端的调用参数根据传输前所提供的目的地址及RPC上层应用程序号,通过底层的RPC传输通道转至相应的服务器,即RPCApplicationPorgrammeServer。客户端随即处于等待状态,以服务器等待应答或TimeOut超时信号。当服务器端获得了请求消息,会根据注册RPC时告诉RPC系统的程序入口地址执行相应的操作,并将结果返回至客户端。当一次RPC调用结束后,相应线程发送相应的信号,客户端程序便继续运行。有三个要素来标识唯一的远程过程:程序号、版本号、过程号。其中,程序号是用来区别一组相关的并且具有唯一过程号的远程过程;一个程序可以有一个或几个不同的版本;而每个版本的程序都包含一系列能被远程调用的过程。同一个版本图6-11RPC的基本操作可以包含有许多可供远程调用的过程,每个过程则有其唯一标示的过程号。通过版本的引入,使得不同版本下的RPC能同时提供服务。2.RPC应用开发从我们上面对于RPC的基本操作看来,RPC的开发一般涉及三方面:⑴定义客户端、服务器端的通信协议。此处的通信协议是指定义服务过程的名称、调用参数的数据类型、返回参数的数据类型、底层传输类型(UDP/TCP)等等。⑵开发客户端程序。⑶开发服务器端程序。对于RPC通信协议的生成,最简单的方法是利用协议编译工具。常用的是rpcgen,不过这是一个用于生成实现RPC协议的C程序的生成器。要使用Java来实现的话,我们需要使用另外的生成器Remotetea。实现RPC要解决的问题:⑴如何在报文中表示不同机型的参数和结果。不同型号的机器,其浮点数和负数的表示以及字节次序可能不同;各机器语言可能用不同的句法和不同的语义表示相似的数据结构;各机器语言可能支持不同的数据结构和过程接口。使用RPC进行通信时,必须在各不同机器之间进行转换工作。其转换工作量可能很大。对于有很多型号机器的系统,常使用一种标准格式,每种机型中的表示都转换成标准格式。但如果双方都使用同一种表示,这种转换就有些浪费。如果使用另一种方法,发送者使用自己的内部格式,让接收者转换成自己的内部表示,那么每种机器必须对其它种机器的每一种进行转换,当机种很多时工作量很大。而且当新机种加入时,很多现有的软件都必须加以补充。⑵RPC透明性带来的服务器定位问题。例如在具有多个文件服务器的系统中,如果一个用户在某个服务器上创建一个文件,则通常希望以后的操(例如写操作)都对该服务器上的那个文件进行。但使用RPC时,该用户只在其程序上设一个过程调用:write(FileDestriptor,BufferAddress,ByteCount);RPC设备试图对用户隐去所有的关于服务器定位的细节。而在这种情况下,这些细节却是十分重要的。⑶广播通信问题。很多应用场合,例如确定某个进程或某种服务的位置,需要广播通信和组通信,即向所有的或若干个目的地而不只是一个目的地发送查询报文,并等待回答。RPC本身并不提供这种机制,语义也是完全不同的。因为RPC是一种同步通信,发送者必须等待每个接收者全部接收完毕。这不仅要等待很长时间,而且发送者并不一定知道共有多少个接收者接收并处理完毕的时间。⑷可靠性语义问题。在计算机网络系统中,RPC并不能总是得到正确的回答,因为通信双方(客户机和服务器)都可能失效,通信线路也可能失效。客户机在向服务器发出一个RPC后,如果由于服务器或信道的故障未得到响应,一定时间后重发RPC;当服务器工作正常而只是客户机未收到回答时,服务器可能重复执行RPC操作;如果客户机在发出RPC后出现故障,而服务器继续执行这一RPC,则成为“孤儿”,客户机恢复后又可能重发这一RPC。从而服务器再次执行这一RPC。在实际应用场合中,RPC的重复执行有时无害,有时是不允许的。例如客户机要求服务器读取某个文件,即使服务器在故障前后执行两次也没什么关系,这叫作重复等效(idempotent)的操作。但是如果一个用户要求从某个银行帐户向另一个帐户转移一笔钱的操作,则要求准确地执行一次,不能执行多次或者不执行。工厂自动生产过程中某些开关的控制要求恰好执行一次RPC,否则会出现故障。所以,发生RPC的多次执行的系统并不总是符合实际应用的需求。因此必须区别不同情况的RPC。RPC可能执行:①恰好一次(Exactly-Once):每次调用时只精确地执行一次,具有和本地过程调用相同的语义;②至少一次(At-Least-Once):用户代理重复发出RPC一直到服务器至少执行了一次;③最多一次(At-Most-Once):通信双方及信道无故障时恰好执行一次并返回一次结果;如果发现服务器崩溃,用户代理将放弃并返回一个错误码,不进行重发。在此情况下,客户机知道操作可能执行0次或一次,不会再多。进一步的恢复由客户机负责。④多次中最后一次语义(Last-of-Many-Call)。这种语义要求给一个调用的每次请求一个顺序号。客户机只接受最近一次请求的返回值。⑤等效语义(Idempotent)。这种语义可以使用有状态服务器,也可以使用无状态服务器。在有多个客户机请求远程过程调用的情况下,这种语义保证不会对结果构成不利影响。对于有状态服务器,服务器所保持的状态不会被多个客户机的请求所破坏。为了使RPC具有“恰好执行一次”或“最多执行一次”的语义。可在客户机的请求报文中设置顺序号,它应与返回结果报文中的顺序号一致。所有重发的报文包含相同的顺序号。服务器拒绝执行具有相同顺序号的请求,或以前的顺序号的请求。为了解决“孤儿”问题,服务器应能检测“孤儿”的产生,并在接受新的RPC之前退回到初始状态(不执行那个RPC操作)。由于RPC调用实际上是实现前面说明的4个问题,所以在RPC设计中,也应当将这4个问题进一步具体化成设计的原则:由于RPC通过网络将被调用过程需要的各种参数进行传递,因此虽然RPC可以传递十分复杂的数据结构,例如链表等,但是这将消耗大量的系统和网络资源。所以应当将RPC调用的接口尽量设计成需要传递的参数较少,且传递的数据结构较简单。例如,在传递多个参数时,可以将它们定义在一个结构中,然后传递结构,这样既有利于程序的可读性,也有利于提高程序的效率。RPC并没有指定使用的传输层端口,并且TCP和UDP都可以使用。当用户使用UDP协议来构建程序时,需要注意UDP协议的不可靠性,对于远程过程的一次调用,将可能导致RPC过程被调用的次数不确定。在使用UDP协议通信时,一个RPC请求报文可能丢失,可能会丢失后重传,所以当一个应用进程收到RPC的回应时,RPC可能被调用了一次或者多次。而当一个应用进程没有收到回应报文时,RPC可能被调用了0次或者多次。由于回应的报文也可能丢失,所以在使用UDP协议实现RPC时,用户应当充分考虑这些问题。ONCRPC(开放网络计算;ONC/RPC也被称为Sun/RPC;支持TCP,UDP)规定:在给定的时刻,一个远程程序中最多可以有一个远程过程被调用,也就是说,在一个给定的程序中,RPC将保证过程调用是互斥的,这一点对于应用端是十分重要的。由于远程过程是在远程的机器上运行,所以一定要保证过程中的语句是适合它所在的运行环境。例如printf语句,由于printf语句希望输入来自于同用户相关的终端,而不是RPC过程所运行的环境;还有对本地系统I/O和文件的访问语句,也不应当出现在远程过程中。总之,RPC的思想来源于本地过程调用,两者都遵守相同的调用原则,只是实现的手段不同。在构造RPC应用时,首先象编写普通的应用那样进行需求分析,这使得用户不会将注意力过早地放在复杂的通信协议上;而后将应用划分为两部分,分别放在顾客端和提供RPC服务的一端。进行划分时,需要尽量的遵循上面的原则,包括在两端传递的参数应当尽量简单,RPC端必须能满足调用所需要的环境等等。用户可以使用系统提供的RPC开发工具加快开发的速度,而直接使用RPC报文的方式来进行应用开发,效率将会很低。RPC同时支持TCP和UDP协议。对于使用UDP协议的RPC应用,由于使用UDP协议的RPC是不可靠的,因此必须使顾客端的程序能够满足“至多被调用了一次”的语义。3.RPC实例当前两个最常用的RPC系统是ONC(开放网络计算)RPC和DCE(分布式计算环境)RPC。ONC/RPC有时也被称为Sun/RPC,由Sun公司开发,它是最早的商用RPC软件之一,ONC/RPC的成功得益于NFS的广泛使用,而NFS正是通过ONC/RPC来实现的。DCE/RPC是由开放软件基金会(OSF)开发的,它是CORBA的一个可选协议,也是COM所使用的一个协议。使用RPC的应用通常采用与CORBA相似的方法,目前支持的程序语言是C。RPC支持持续性服务器策略,这种服务器一直运行,同时RPC又支持独享服务器策略,这时每一次呼叫都生成一个服务器进程。ONC/RPC支持的传输协议是TCP和UDP,DCE/RPC同时也支持DECNET,ONC/RPC信息传递的可靠性由下层协议保证,而DCE/RPC则保证了信息的传递,并且与具体的传输协议无关。ONC/RPC使用XDR协议来实现异种计算机之间的数据传输,它使用单一的格式来传递数据,而DCE/RPC使用NDR,总共有l6种格式,发送者指定所发送的格式,接收者负责数据的解释。ONC/RPC的安全性(称为安全RPC)通过NIS+来实现,NIS+提供授权和鉴别功能,在名字空间内,每一个对象都指定它能接收的对象,以及从什么对象接收等。总共有三个层次的鉴别级别:⑴无安全性。⑵传统进程许可机制—提供uid、gid、补充组、机器名等。⑶提供标识验证机制(基于Diffie/Hellman的DES加密密钥发布技术)。DCE/RPC提供鉴别、授权、访问控制服务,客户机和服务器都能被鉴别,授权服务允许一个用户、主机、服务器来决定其他用户、主机、服务器等的权限。ONC/RPC使用NIS+来处理全局名字服务,NIS+用来把一个服务和它的名字、所在域等联系起来。NIS+表通过NIS+管理命令来管理,名字空间被配置成域,域包括目录、表格和组(称为对象),每一个域由一组NIS+服务器支持,NIS+服务器用来处理客户机的请求,NIS+维持一个包含RPC程序名、程序号和别名的表格。DCE/RPC使用一种基于X.500目录服务(XDS)的全局目录服务(GDS),使用GDS可以提供服务全球资源的功能,GDS为各种网络服务和计算机提供查名服务,服务器输出(export)它们的绑定(binding),包括RPC协议类型、主机网络地址、传输终点等信息,以及其他GDS所必需的对象。一个能支持多重RPC协议的服务器需要为每一个协议输出有关绑定,客户机通过使用自动绑定,利用GDS获得有关服务器的信息。下面这段代码给出了一个方法,当不使用RPC时,如何获得远程计算机时间。intremote_time(charmachine,chartime_buf){structsockaddr_inserv_addr;intsockfd:intnread;if(sockfd=socket(AF_INET,SOCK_STREAM,0))<0)return1;serv_addr.sin__family=AF_INET;serv_addr.sin_addr.s_addr=inet_addr(machine);serv_addr.sin.port=htons(13);if(connect(sockfd,&serv_addr,sizeof(serv_addr))<0)return2;nread=read(sockfd,time_buf,sizeof(time_buf));time_buf[nread]=’\\0’close(sockfd);return0;如果使用RPC调用,则和本地时间调用相似,所有网络调用由RPC完成,客户机只要简单地调用remote_time(machine,time_buf)即可。而在远程计算机上时间调用的实现如下所示:intremote_time(chartime_buf){structtmtime;time_tt:time(&t);time=localtime(&t);strcpy(time_buf,asctime(time));return0;}正如我们上面的讨论过的要实现RPC要解决的问题,除了常规过程调用的错误外,RPC还有以下所特有的故障:⑴找不到服务器。如果没有服务器,必须返回相应的故障信息,返回方式和具体语言密切相关,不同语言使用不同的方法。⑵丢失到服务器的请求。通常的解决办法是客户机端程序设置一个计时器,超时后重新发送信息,直到成功或超过最大计数为止,这时返回一个错误信息。如果实际上信息并没有丢失,只是网络太慢,这样服务器就可能接收到多个请求,可能会进行多次操作,存在潜在的故障。其解决办法是在每一个请求中设置一个请求标识,不同的请求有不同的标识;而同一个请求的标识相同,这样服务器即使收到多次请求,也能通过标识来决定是否已经处理过这个请求,若已经处理过,则不再进行第二次处理,只需把结果重新发送一次即可。⑶丢失服务器给客户机的回答。解决办法和上述相似。⑷服务器死机。在这种情况下,当服务器恢复运行后,服务器可能没有保持它所接受的信息,可能重新运行,这在某些情况下(比如银行经费转移等)是不允许的。(5)客户机死机。可以通过在本地记录所发送的每一个RPC信息来解决,尽管速度比较慢。6.3.3实时传输协议实时传输协议RTP(Real-timeTransportProtocol)。它是IETF提出的一个标准,对应的RFC文档为RFC3550(RFC1889为其过期版本)。RFC3550不仅定义了RTP,而且定义了配套的相关协议实时传输控制协议RTCP(Real-timeTransportControlProtocol)。RTP用来为IP网上的语音、图像、传真等多种需要实时传输的多媒体数据提供端到端的实时传输服务。RTP为Internet上端到端的实时传输提供时间信息和流同步,但并不保证服务质量,服务质量由RTCP来提供。1.RTP/RTCP简介RTP由IETF的AVT工作组于1996年公布为RTP正式文档,是专门为交互式话音、视频、仿真等实时媒体数据的端到端传输服务而设计的轻型传输协议。其中RTP以报文形式携带着媒体数据,而RTCP则利用RTP报文的相关传输质量信息构成RTCP报文,以监视服务质量并传送正在进行的会话中参与者的信息。它们能提供的服务类型则包括有效载荷类型标识、顺序号、时间戳、传送监测。RTP包含两个紧密联系的部分:⑴RTP(Real-timeTransportProtocol),用于携带具有实时特性的数据;⑵RTCP(RTPControlProtocol),用于监视服务质量并传送正在进行的会话中参与者的信息。RTCP和RTP一起提供流量控制和拥塞控制服务。以建立在UDP上的应用为例通常在程序启动时,会打开两个连续的端口,偶数端口给RTP,奇数端口给RTCP。在RTP会话期间,各参与者周期性地传送RTCP包。RTCP包中含有已发送的数据包的数量、丢失的数据包的数量等统计资料,因此,服务器可以利用这些信息动态地改变传输速率,甚至改变有效载荷类型。RTP和RTCP配合使用,它们能以有效的反馈和最小的开销使传输效率最佳化,因而特别适合传送网上的实时数据。如图6-12所示。RTP协议被IESG(InternetEngineeringSteeringGroup)采纳为Internet标准以后,包括Microsoft和Intel等公司在内的全球逾百家厂商联合签署协议,共同致力于建立一个基于RTP/RTCP协议的开放性平台,“使基于Internet的音频、视频及数据通信变得象打电话一样简单”。国外的研究机构如美国哥伦比亚大学、贝尔实验室和德国国家信息技术研究中心等也都开展了大量基于RTP/RTCP协议的研究和实验。基于RTP/RTCP协议的网络多媒体应用工具和产品也已大量涌现。2.RTP的应用环境RTP用于在单播或多播网络中传送实时数据。它们典型的应用场合有如下几个。⑴简单的多播音频会议。语音通信通过一个多播地址和一对端口来实现。一个用于音频数据(RTP),另一个用于控制包(RTCP)。⑵音频和视频会议。如果在一次会议中同时使用了音频和视频会议,这两种媒体将分别在不同的RTP会话中传送,每一个会话使用不同的传输地址(IP地址+端口)。如果一个用户同时使用了两个会话,则每个会话对应的RTCP包都使用规范化名字CNAME(CanonicalName)。与会者可以根据RTCP包中的CNAME来获取相关联的音频和视频,然后根据RTCP包中的计时信息(Networktimeprotocol)来实现音频和视频的同步。⑶翻译器和混合器。翻译器和混合器都是RTP的中继系统。翻译器用在通过IP多播不能直接到达的用户区,例如发送者和接收者之间存在防火墙。当与会者能接收的音频编码格式不一样,比如有一个与会者通过一条低速链路接入到高速会议,这时就要使用混合器。在进入音频数据格式需要变化的网络前,混合器将来自一个源或多个源的音频包进行重构,并把重构后的多个音频合并,采用另一种音频编码进行编码后,再转发这个新的RTP包。从一个混合器出来的所有数据包要用混合器播放A/V服务器数据信息RTP/UDP控制信息RTCP/TCP(UDP)图6-12RTP/RTCP建立在UDP上的应用作为它们的同步源(SSRC,见RTP的封装)来识别,可以通过贡献源列表(CSRC表,见RTP的封装)可以确认谈话者。3.RTP的协议层次RTP是用来提供实时传输的,因而可以看成是传输层的一个子层。图6-13给出了流媒体应用中的一个典型的协议体系结构。图6-14给出了RTP协议与其他协议之间的关系。从图6-13中可以看出,RTP被划分在传输层,它建立在UDP上。同UDP协议一样,为了实现其实时传输功能,RTP也有固定的封装形式。RTP用来为端到端的实时传输提供时间信息和流同步,但并不保证服务质量。服务质量由RTCP来提供。不少人也把RTP归为应用层的一部分,这是从应用开发者的角度来说的。操作系统中的TCP/IP等协议栈所提供的是我们最常用的服务,而RTP的实现还是要靠开发者自己。因此从开发的角度来说,RTP的实现和应用层协议的实现没有什么不同。图6-13流媒体体系结构应用程序RTP/RTCPUDPTCPIPV4/IPV6局域网/广域网图6-14RTP协议与其他协议的关系RTP实现者在发送RTP数据时,需先将数据封装成RTP包,而在接收到RTP数据包,需要将数据从RTP包中提取出来。4.RTP的头部格式RTP的头部格式如图6-15所示。版本号(V):2比特,用来标志使用的RTP版本。填充位(P):1比特,如果该位置位,则该RTP包的尾部就包含附加的填充字节。扩展位(X):1比特,如果该位置位的话,RTP固定头部后面就跟有一个扩展头部。CSRC计数器(CC):4比特,含有固定头部后面跟着的CSRC的数目。标记位(M):1比特,该位的解释由配置文档(Profile)来承担。载荷类型(PT):7比特,标识了RTP载荷的类型。序列号(SN):16比特,发送方在每发送完一个RTP包后就将该域的值增加1,接收方可以由该域检测包的丢失及恢复包序列。序列号的初始值是随机的。时间戳:32比特,记录了该包中数据的第一个字节的采样时刻。在一次会话开始时,时间戳初始化成一个初始值。即使在没有信号发送时,时间戳的数值也要随时间而不断地增加(时间在流逝嘛)。时间戳是去除抖动和实现同步不可缺少的。同步源标识符(SSRC):32比特,同步源就是指RTP包流的来源。在同一个RTP会话中不能有两个相同的SSRC值。该标识符是随机选取的,RFC1889推荐了MD5随机算法。贡献源列表(CSRCList):0~15项,每项32比特,用来标志对一个RTP混合器产生的新包有贡献的所有RTP包的源。由混合器将这些有贡献的SSRC标识符插入表中。SSRC标识符都被列出来,以便接收端能正确指出交谈双方的身份。5.RTCP的封装RTCP的主要功能是:服务质量的监视与反馈、媒体间的同步,以及多播组中成员的标识。在RTP会话期间,各参与者周期性地传送RTCP包。RTCP包中含有已发送的数据包的数量、丢失的数据包的数量等统计资料,因此,各参与者可以利用这些信息动态地改变传输速率,甚至改变有效载荷类型。RTP和RTCP配合使用,图6-15RTP的头部格式V=2PXCCMPT序列号时间戳同步源标识(SSRC)提供源标识(CSRC)…它们能以有效的反馈和最小的开销使传输效率最佳化,因而特别适合传送网上的实时数据。RTCP也是用UDP来传送的,但RTCP封装的仅仅是一些控制信息,因而分组很短,所以可以将多个RTCP分组封装在一个UDP包中。RTCP有如下五种分组,如表6-4所示。表6-4RTCP的5种类型类型缩写表示用途200SR(SenderReport)发送端报告201RR(ReceiverReport)接收端报告202SDES(ScurceDescriptionItems)源点描述203BYE结束传输204APP特定应用上述五种分组的封装大同小异,下面只讲述SR类型,而其它类型请参考RFC3550。发送端报告分组SR(SenderReport)用来使发送端以多播方式向所有接收端报告发送情况。SR分组的主要内容有:相应的RTP流的SSRC,RTP流中最新产生的RTP分组的时间戳和NTP,RTP流包含的分组数,RTP流包含的字节数。SR包的封装如图6-16所示。图6-16RTCP头部的格式版本(V):同RTP包头域。填充(P):同RTP包头域。接收报告计数器(RC):5比特,该SR包中的接收报告块的数目,可以为零。包类型(PT):8比特,SR包是200。长度域(Length):16比特,其中存放的是该SR包以32比特为单位的总长度减1。同步源(SSRC):SR包发送者的同步源标识符。与对应RTP包中的SSRC一样。NTPTimestamp(Networktimeprotocol)SR包发送时的绝对时间值。NTP的作用是同步不同的RTP媒体流。RTPTimestamp:与NTP时间戳对应,与RTP数据包中的RTP时间戳具有相同的单位和随机初始值。Sender’spacketcount:从开始发送包到产生这个SR包这段时间里,发送者发送的RTP数据包的总数。SSRC改变时,这个域清零。Sender`soctetcount:从开始发送包到产生这个SR包这段时间里,发送者发送的净荷数据的总字节数(不包括头部和填充)。发送者改变其SSRC时,这个域要清零。同步源n的SSRC标识符:该报告块中包含的是从该源接收到的包的统计信息。丢失率(FractionLost):表明从上一个SR或RR包发出以来从同步源n(SSRC_n)来的RTP数据包的丢失率。累计的包丢失数目:从开始接收到SSRC_n的包到发送SR,从SSRC_n传过来的RTP数据包的丢失总数。收到的扩展最大序列号:从SSRC_n收到的RTP数据包中最大的序列号,接收抖动(Interarrivaljitter):RTP数据包接受时间的统计方差估计上次SR时间戳(LastSR,LSR):取最近从SSRC_n收到的SR包中的NTP时间戳的中间32比特。如果目前还没收到SR包,则该域清零。上次SR以来的延时(DelaysincelastSR,DLSR):上次从SSRC_n收到SR包到发送本报告的延时。6.RTP的会话过程当应用程序建立一个RTP会话时,应用程序将确定一对目的传输地址。目的传输地址由一个网络地址和一对端口组成,有两个端口:一个给RTP包,一个给RTCP包,使得RTP/RTCP数据能够正确发送。RTP数据发向偶数的UDP端口,而对应的控制信号RTCP数据发向相邻的奇数UDP端口(偶数的UDP端口+1),这样就构成一个UDP端口对。RTP的发送过程如下,接收过程则相反。⑴RTP协议从上层接收流媒体信息码流(如H.263),封装成RTP数据包;RTCP从上层接收控制信息,封装成RTCP控制包。⑵RTP将RTP数据包发往UDP端口对中偶数端口;RTCP将RTCP控制包发往UDP端口对中的接收端口。RTP根据应用程序的要求将流媒体数据包封装成RTP数据包并进行发送;它靠上层的调用以及依赖网络层发送来实现;工作时,RTP协议从上层接收流媒体信息码流装配成RTP数据包发送给下层,下层协议提供RTP和RTCP的分流。RTP数据包没有长度限制,它的最大包长只受下层协议的限制。RTCP报文不封装音视频数据,而是封装发送端或者接收端的统计报表信息。在RTP会话期间,每个参与者周期性的向其它参与者发送RTCP控制信息包,如图6-17所示:因为网络的情况很不稳定,如果网络情况好我们可以减少语音的延迟时间,也可以增大视频的发送帧率或质量。若网络状况不好我们可以增大语音延迟时间以保证语音连续,也可减少视频的发送帧率或质量,以减少网络的阻塞。RTCP包的发送率根据与会者的数量来调整。7.RTP协议关键技术指标⑴时间戳时间戳反映了RTP分组中的数据的第一个字节的采样时刻。在一次会话开始时的时间戳初值也是随机选择的。即使是没有信号发送时,时间戳的数值也要随时间不断的增加。接收端使用时间戳可准确知道应当在什么时间还原哪一个数据块,从而消除传输中的抖动。时间戳还可用来使视频应用中声音和图像同步。⑵时延影响时延的因素有多个方面:编解码、网络、防抖动缓冲、报文队列等都影响时延,其中有些是固定时延,如编解码网络速率等;有些是变化的,如防抖动缓冲和队列调度等,固定的时延可以通过改变编解码方式和提高网络速率来改变,而变化的时延通常采用提高转发效率来提高。⑶抖动发送端RTPRTCP接受端接受端INTERNETRTCPRTCP图6-17RTCP工作示意图在视频电话中,语音、视频数据都是使用UDP协议传送的,但这种协议传输的数据包在网络层不能保证其发送顺序,需要应用层进行排序。在网络的传输中都会有延时,且随着网络负载的变化,延时的长短也不相同,对于语音数据,如果接收方收到后立即播放,很容易造成语音的抖动。为了更好的解决抖动的问题,最好能实现抖动缓存,一是保证语通道读取数据包的顺序正确,二是控制接收方按照采集的时间顺序播放语音,减少语音的抖动;另外提供QoS和资源预留使语音数据获得优先发送和获得固定的带宽也是解决抖动问题的主要手段。⑷丢包率丢包率是通过计算接收包数量和发送包数量的比率得到的,丢包率获得的整个流程是:发送方每间隔一定时间读取每个发送通道的发包数量和数据长度,组成一个此通道的RTCP报文发送给接收方,同时将发送数据包计数清零;接收方收到RTCP包后,读取接收通道接收到的包数量,并计算出丢包率,通过一个RTCP接收汇报包发送给发送方,同时对接收数据包计数清零。⑸会话和流两级分用一个RTP会话(Session)包括传给某个指定目的地对(DestinationPair)的所有通信量,发送方可能包括多个。而从同一个同步源发出的RTP分组序列称为流(Stream),一个RTP会话可能包含多个RTP流。一个RTP分组在服务器端发送出去的时候总是要指定属于哪个会话和流,在接收时也需要进行两级分用,即会话分用和流分用。只有当RTP使用同步源标识(SSRC)和分组类型(PTYPE)把同一个流中的分组组合起来,才能够使用序列号(SequenceNumber)和时间戳(Timestamp)对分组进行排序和正确回放。⑹多种流同步控制RTCP的一个关键作用就是能让接收方同步多个RTP流,例如:当音频与视频一起传输的时候,由于编码的不同,RTP使用两个流分别进行传输,这样两个流的时间戳以不同的速率运行,接收方必须同步两个流,以保证声音与影像的一致。为能进行流同步,RTCP要求发送方给每个传送一个唯一的标识数据源的规范名(CanonicalName),尽管由一个数据源发出的不同的流具有不同的同步源标识(SSRC),但具有相同的规范名,这样接收方就知道哪些流是有关联的。而发送方报告报文所包含的信息可被接收方用于协调两个流中的时间戳值。发送方报告中含有一个以网络时间协议NTP(NetworkTimeProtocol)格式表示的绝对时间值,接着RTCP报告中给出一个RTP时间戳值,产生该值的时钟就是产生RTP分组中的TimeStamp字段的那个时钟。由于发送方发出的所有流和发送方报告都使用同一个绝对时钟,接收方就可以比较来自同一数据源的两个流的绝对时间,从而确定如何将一个流中的时间戳值映射为另一个流中的时间戳值。8.RTP协议应用方案⑴RTP协议应用方案之单播在客户端与媒体服务器之间建立一个单独的数据通道,从一台服务器送出的每个数据包只能传送给一个客户端,这种传送方式称为单播。优点:便于控制和管理;缺点:每个用户必须分别对媒体服务器发送单独的查询,而媒体服务器必须向每个用户发送所申请的数据包拷贝。这种巨大冗余造成服务器负担沉重,响应需要很长时间。⑵RTP协议应用方案之广播广播指的是用户被动地接收流。在广播过程中,数据包的单独一个拷贝将发送给网络上的所有用户,客户端接收流,但不能控制流;广播方式中资料包的单独一个拷贝将发送给网络上的所有用户,而不管用户是否需要,会非常浪费网络带宽。优点:简单;缺点:浪费网络带宽。⑶RTP协议应用方案之组播组播技术构建的网络,允许路由器一次将数据包复制到多个通道上。采用组播方式,媒体服务器只需要发送一个信息包,所有发出请求的客户端即可同时收到连续数据流而无延时。这就大大减少了网络上传输的信息包的总量,组播吸收了单播和广播两种发送方式的长处,克服了上述两种发送方式的弱点,将资料包的单独一个拷贝发送给需要的那些客户。组播不会复制资料包的多个拷贝传输到网络上,也不会将资料包发送给不需要它的那些客户,保证了网络上多媒体应用占用网络的最小带宽。优点:减少网络上传输的信息包的总量。网络利用效率大大提高,成本大为下降;缺点:当不同的用户同时点播同一个节目时,由于点播总有先后顺序,后点播的用户并不是从开始播放,而是依照网络中同时点播此节目的其它用户的播放进度,这就造成当前用户极有可能从节目的中间开始看起,很难做到个性化。6.4Internet传输协议—TCP面向连接的协议在两个对等端内部之间直接建立逻辑连接。它通过跟踪数据的传送,并确认和跟踪序号来确保它成功到达接受方。确认是一种积极响应,表明数据已经到达。面向连接的对等端使用序号跟踪确定发送的数据量和任何无序数据包。面向连接的协议中有超时机制,它的作用是当主机等待的时间太长时就认为是数据丢失。它还有重试机制,用来按一定的重复次数重发丢失的数据。TCP是一种面向连接的协议。依赖到达目的地的数据的应用程序使用的是TCP而不是UDP。6.4.1TCP介绍TCP(TransmissionControlProtocol)传输控制协议,是专门为了在不可靠的网络互联上提供可靠的端到端的字节流而设计的,互联网络与单个网络不同,因为互联网络的不同部分可能有截然不同的拓扑、带宽、延迟、分组大小和其他的参数。TCP的设计目标是能够动态地适应互联网络的这些特性,而且当面对多种失败的时候依然足够健壮。TCP的原始正式定义位于RFC793中。随着时间的推移,各种错误和不一致性逐渐被检测出来,而且在某些领域中需求也发生了变化。RFC1122详细地阐述了这些内容以及一些错误修补方案。RFC1323又进一步作了扩展。毎台支持TCP的机器都有一个TCP传输实体,它或者是一个库过程,或者是一个用户进程,或者是内核的一部分。在所有这些情形下,它管理TCP流,以及与IP层之间的接口。TCP传输实体接受本地进程的用户数据流,并且将它们分割成不超过64KB(在实践中,考虑到在每个帧中都希望有IP头和TCP头,所以通常不超过1460数据字节)的分片,然后以单独的IP数据报的形式发送每一个分片。当包含TCP数据的数据报到达一台机器的时候,它们被递交给TCP传输实体,然后TCP传输实体再重构出原始的字节流。IP层并不保证数据报一定被正确地递交到目标端,所以,TCP需要判断超时的情况,并且根据需要重传数据报。即使被正确递交的数据报,也可能存在错序的问题,所以,这也是TCP的责任:它必须把接收到的数据报按照正确的顺序重新装配成用户的消息。简而言之,TCP必须提供可靠性,这也正是大多数用户所期望的而IP又没有提供的功能。和UDP一样,TCP提供了多路复用、多路分解和错误检测。但是,TCP和UDP在很多方面还有差别。最基本的差别就是,UDP是无连接的,而TCP是面向连接的。由于UDP不需要建立任何连接,所以它被称为无连接的。TCP在一个应用进程向另一个应用进程发送数据之前,两个进程之间必须互相“握手”,也就是说,它们必须为后来的数据传输参数的建立发送一些预备数据段。TCP“连接”不像线路交换网络中的端到端的TDM或者FDM电路。而且,它也不是一个虚电路,因为连接状态是完全驻留在两个终端系统中的。由于TCP协议仅仅在终端系统中、而不在网络的中间元件(路由器和网桥)中运行,所以网络中间元件不需要保留TCP连接的状态。事实上,中间路由器对于TCP连接来说可以完全被忽略掉;这些路由器只关心那些自带寻址信息的分组,而那些连接对它们毫无意义。TCP连接提供了全双工数据传输。如果在一个主机上的进程A和另一个主机上的进程B之间存在一个TCP连接,那么应用程序级的数据可以在A和B之间同时双向传输。TCP连接也是点到点的,也就是说,它存在于单个发送方和单个接收方之间。所谓的“多点传送”,即在一个发送操作中,执行一个发送方到多个接收方的数据传送,在TCP中是不可能实现的。现在让我们看一下TCP连接是如何建立的。假设运行在一台主机上的一个进程想要建立和另一台主机上运行的进程之间的TCP连接。发起连接的进程被称为客户进程,而另外一个进程被称为服务器进程。客户应用程序进程首先通知客户端TCP它想要和服务器进程之间建立一个连接。然后,客户端的传输层继续和服务器上的TCP建专立TCP连接。本节的后面(6.4.3节)将详细地讨论连接建立的过程。现在我们知道这些就足够了:客户端首先发送一个专用的TCP数据段;服务器以第二个TCP数据段作为应答;最后客户端再次以第三个TCP数据段作为应答。前两个数据段不包含任何“有效载荷”,也就是说,没有应用程序层的数据;第三个数据段可以传送有效载荷。由于两个主机之间传送的这三个数据段,这个连接的建立过程通常被称为三次握手。一旦TCP连接建立了,那么由于TCP是全双工的,双方可以同时发送数据,所以这两个应用程序之间就可以互相传送数据了。接下来,就开始由客户端运行的TCP来支配了。TCP将这些数据存入连接的发送缓冲区,这是在最初的三次握手协议中没有用到的缓冲区之一。TCP规范[RFC793]规定了TCP应该“在方便的时候用数据段的方式发送数据”。最大数据段尺寸(maximumsegmentsize,MSS)对每次放入数据段中的最大数据量进行了限制。TCP用一个TCP头部将每一块客户数据进行了封装,这样就得到了TCP数据段。这些数据段被传送到下面的网络层,在那里它们被分别封装到网络层IP数据报中。然后这些IP数据报被送到网络中。当TCP在另一端接收到了一个数据段,该数据段中的数据就被放入TCP连接的接收缓冲区中。应用程序从这个缓冲区中读出数据。连接的每一方都有其自己的发送缓冲区和接收缓冲区。6.4.2TCP数据段的格式数据段是TCP规范中最重要的组件,连接和数据传输服务的整个框架都是围绕这个很小但却很重要的组件建立的。除了被传输的数据,数据段还包含重要的信息和指令,这些信息和指令存放在数据段中称为段头的第一部分中。这些信息包括源和目标端口、序号和确认号、段长、要传输的数据以及给接收端的各种指令。接收端上的应用使用这些指令来处理段中的附加信息、校验数据段中数据的真实性并控制段的大小。图6-18所示为TCP数据段格式。图6-18TCP数据段格式每个TCP数据段都包括源和目的端的端口号,用于标识发送端和接收端的应用进程。顺序号用来标识从TCP发送端向接收端发送的数据字节流,它表示在这个数据段中的第一个数据字节序号。确认号是指规定了成功收到的数据段的序号,这些序号是递增的。这些号码是和一个确认数据段一起发送的,该确认段用来确认另一个段的接收。这些递增的序号表明序号低于该确认号的数据段已经被成功收到。此号码也表明了将要被传输的数据段序列中下一数据段的序号。头部长度字段占4位,用来标识TCP数据段首部的长度共有多少个32位字块构成,因此首部的长度一定是32位的整数倍。保留字段目前未用,供将来使用。其后面的6位是控制字段,用于TCP的流量控制、连接的建立和终止以及表示数据的传送方式等。各位的具体含义如下:URG:告诉接收端数据段的紧急指针字段是有效的,并且数据段必须被立即定向到应用中,而不是被缓冲起来,因为数据段中含有紧急信息,当该位为1时,表明紧急指针有效,否则无效。ACK:告诉接收端数据段头的确认字段是一个有效字段,必须使用它来获取确认号,因为所有的数据段都不使用确认号字段来传输确认号,当该位为1时,表明确认序号有效,即该数据段是一个确认数据段,否则无效。PSH:告诉接收端将接收到的有效段立即发给应用,不要将其放到缓冲区中。另外,PSH还实现了数据段的立即传输,不用等待构建成一个大的数据块后再传输。因此,推操作(PushAction)同时发生在连接的两端,即发送端和接收双端上其值为1时表示接收方应尽快将这个数据段交给应用层处理。RST:告诉接收端立即终止一条连接并释放与连接相关的资源,比如缓冲区。SYN:表示和数据段一起发送的序号用来保证发送端和接收端计算机上的序号同步。当用来建立连接的初始数据段在发送端和接收端间进行交换时,就需要用到SYN标志。这些初始数据段也叫SYN数据段,其值为1时用来发起一个连接。FIN:说明该数据段是接收端收到的数据段序列中的最后一个数据段。设置了FIN标志的最后一个数据段也被称为FIN段,值为1时表示发送端完成了发送任务。窗口指定了关于发送端能传输的下一数据段的大小的指令。这个指令是专为发送端准备的,并且在确认消息被发往给发送端时,和ACK标志一起包含在段头中。校验和被用做一个校验机制,包含了源和目标计算机的IP地址、底层传输层协议(TCP或UDP)等信息,以及整个TCP段(包括段头和数据部分)的长度信息。紧急指针(UrgentPointer)指明段中包含有紧急信息,在到达接收端后,必须被立即处理,而不是放入缓冲区中。必须设置代码位中的URG标志才能使用此特性。选项段头字段在数据的有效传输过程中扮演了重要的角色。该字段中可以设置四个选项:字段结束(EndofField)、空操作(NoOperation)、最大段尺寸(MaximumSegmentSize)和时间戳(Timestamp)。表6-5简要地描述了各个选项类型。表6-5设置在选项字段中的选项类型选项类型描述字段结束指定了数据段头选项字段的结束空操作指定了选项字段中一个选项的结束和另一个选项的开始最大段尺寸由发送端指定,表明了能在网络上传输的最大的数据段尺寸。这个选项是最常用的一个选项,作为建立连接的第一段中的一部分被发送时间戳记录了数据段第一次被发送给接收端的时间。此选项也能用来记录发送确认消息的时间。TCP段头中另一个重要的字段是校验和(Checksum)字段。该字段用来校验数据段的头部以及数据部分的可靠性。校验和包含五个部分,分别存储了下面的这些值:源IP地址、目标IP地址、底层协议、段头长度和校验和的值。这些值分别存储在源地址、目标地址、零(Zero)、协议和TCP长度组件中。接收端计算机通过检验校验和值来确保收到的段在传输过程中未被修改或损坏。TCP也为段中的数据部分创建了一个校验和。图6-19所示的是TCP校验和字段中的内容。值得注意的重要一点是,TCP段并不是作为一个单独的数据单元在发送和接收计算机间传输的。在传输给另一台机器前,TCP报文段被封装在IP数据报中,整个TCP数据段作为IP数据报的数据被封装在IP数据报中。图6-20说明了TCP段是如何被封装的。6.4.3TCP连接管理在这个小节中,我们较为深入地看一下如何建立和拆除一个TCP连接。我们在6.2.2节中已经讨论过这个话题,但是它很重要,因为TCP连接的建立会显著地增加延迟(如,在浏览网页的时候)。图6-19TCP校验和字段中的内容图6-20TCP数据段封装1.建立连接现在,让我们来看一下如何建立一个TCP连接。假设运行在一个主机(客户)上的进程想要创建和另一个主机(服务器)上的进程之间的连接。客户应用程序进程首先通知客户TCP,它想要建立一个和服务器上的进程之间的连接。客户端的TCP就会用以下方式和服务器上的TCP建立TCP连接:⑴第一步客户端TCP首先给服务器端TCP发送一个特殊的TCP数据段。该特殊的数据段不包含应用层数据。当然,它需要将该数据段的头部中的一个标志字段,称为SYN,设置为l。由于这个原因,这个数据段就被称为SYN数据段。另外,客户会选择一个初始顺序号(client_isn),并将这个编号放到初始的TCPSYN数据段的顺序号字段中。该数据段被封装到一个IP数据报中,并发送给服务器。⑵一旦装有TCPSYN数据段的IP数据报到达了服务器主机(假设它能到达),服务器将从该数据报中提取出TCPSYN数据段,给该连接分配TCP缓冲区和变量,并给客户TCP发送一个允许连接的数据段。这个允许连接数据段也不包含任何应用层数据。但是,它的头部中装载着3个重要信息。首先,SYN被设置为l。其次,TCP数据段头部的确认字段被设置为client_isn+1。最后,服务器选择它自己的初始顺序号(server_isn)并将该值放到TCP数据段头部的顺序号字段中。这个允许连接数据段有效地说明了:“我已经接收到了带有初始顺序号的要求开始连接的SYN分组,client_isn。我同意建立这个连接。我自己的初始顺序号为server_isn”。这个允许连接数据段有时被称为SYNACK数据段。⑶第三步在接收到允许连接数据段之后,客户也会给连接分配缓冲区和变量。客户端主机还会给服务器发送另外一个数据段;这最后一个数据段对服务器的允许连接数据段给出确认(客户通过将值server__isn+1放入TCP数据段头部的确认字段中来完成这项工作)。因为连接建立了,所以SYN被设置为0。当以上的三步都完成之后,客户和服务器主机就可以互相发送装载有数据的数据段了。在以后的每一个数据段中,SYN都会被设置为0。注意,为了建立连接,在两个主机之间需要传送3个分组,正如图6-21中所示那样。由于这个原因,连接建立的过程通常被称为三次握手。2.释放连接所有的事情都应该有结尾,TCP连接也不例外。参与TCP连接的两个进程中的任何一个都可以终止该连接。当连接结束之后,主机上的“资源”(即缓冲区和变量)将会被释放。例如,假设客户想要终止该连接,如图6-22所示。客户应用程序进程就会发出一个结束命令。这个特殊的数据段的头部中有一个比特标志位,称为FIN(见图6-18),被设置为1。当服务器接收到这个数据段,它就会回送给客户一个确认数据段。然后,服务器发送它自己的终止数据段,其中FIN被设置为l。最后,客户对服务器的终止数据段给出确认。这时,两个主机上的所有资源都被释放。客户连接请求(SYN=1,seq=client_isn)授予连接(SYN=1,seq=client_isn)ACK=client_isn+1确认(SYN=0,seq=client_isn)ACK=server_isn+1时间时间服务器图6-21TCP三次握手:数据段互换3.配置最大段尺寸初始数据段不仅包含序号,而且还指示接收端必须将数据段分成一定大小尺寸的分段。这个指令存储在数据段头选项字段的最大段尺寸字段中。TCP数据段被包含在IP数据报中。之所以需要确定MSS的值是因为数据段的大小会影响IP数据报的大小,且这些数据报还可能要在不同的网络上传输。一些网络可能是高速网,能支持较大的数据报,如果在这样的高速网上传输小数据段,那么就不能充分利用网络资源。例如,仅包含了1个字节的数据段被打包到有20个字节数据的TCP报头中,并且IP数据报也有20个字节。这意味着为了传输1个字节的数据,却动用了40个额外的字节,这将导致网络带宽的利用率严重低下。另一方面,如果在低速网上传输大数据段,那么包含段的数据报必须被分段后才能传输。将数据报分段降低了数据传输的可靠性,因为如果一个数据报分段丢失了,那么弥补数据分段丢失的损失没有别的方法,只能重传该数据报所有分段。决定MSS的另一个因素是所连接的计算机的缓冲区大小。假设一台缓冲区大小有限的计算机请求具有较大缓冲区的计算机上的数据,那么发送端计算机的高数据传输能力很容易阻塞请求计算机有限的缓冲区。因此,段的大小必须被优化以满足双方对缓冲区的需求。为了解决这些问题,三方握手过程中,双方计算机会交换MSS值。FINACK关闭FINACK计时等待已关闭时间图6-22关闭一个TCP连接客户服务器每个网络都设置有一个最大传输单元(MTU)值,用来决定它的最大数据单元传输能力。当同一个网络上的计算机互相通信时,MSS的值可以根据网络所支持的MTU值来计算。然而,如果不同网络上的计算机要互相通信,确定MSS最优值的方法仅有一种,即通过使用一个初始IP数据报作为探测器去侦测网络的MTU。这个探测数据报的IP报头标志字段必须被设置为1,以表明禁止数据报分段。如果IP探测器没有被分段就到达了目的地,那么就会采用此探测器段中用到的MSS值,用做将来的数据传输。然而,如果ICMP发送了一个表示数据报已经被分段的报文,MSS的值就会被重新计算出一个新值,另一个设置了这个新值的探测器就被发送出去为分段做测试。如果需要在不同的网络上传输数据,也可以设置成536字节的MSS默认值。4.TCP连接状态在一个TCP连接的整个生命周期中,每一个主机上运行的TCP协议都经过了各种TCP状态。图6-23描述了客户TCP所经历的一个典型的TCP状态序列。客户TCP在关闭的状态下开始。客户端的应用程序初始化一个新的TCP连接(在6.1.4节的例子中是通过创建一个Socket对象来实现的)。这就使得客户TCP给服务器TCP发送一个SYN数据段。在发送SYN数据段之后,客户TCP就进入了SYN_SENT状态。在SYN_SENT状态中,客户TCP等待着从服务器TCP发送的、对客户上一次发送的数据段的确认数据段,而且在该数据段中,SYN也被设置为l。一旦接收到这个数据段,客户TCP进入ESTABLISHED(已建立)状态。而在ESTABLISHED状态中,TCP客户就可以发送和接收装载着有效载荷数据的TCP数据段了。假设客户应用程序决定要终止该连接(注意,服务器也可以选择终止连接)。这图6-23客户端TCP状态序列使得客户TCP发送一个FIN被置为l的TCP数据段并且进入到FIN_WAIT_1状态。在FIN_WAIT_1状态中,客户TCP等待着从服务器发来的带有确认的TCP数据段。当它接收到该数据段,客户TCP进入FIN_WAIT_2状态。在FIN_WAIT_2状态中,客户等待着服务器的另一个FIN被设为1的数据段;在接收到该数据段之后,客户TCP对服务器的数据段给出确认并且进入TIME_WAIT状态。在TIME_WAIT状态中,如果TCP客户最后一次发送的ACK丢失了,它将重新发送。TIME_WAIT状态中所需要的时间是依赖于实现方法的,典型的值为30秒、l分钟和2分钟。等待之后,连接正式关闭并且客户端的所有资源(包括端口号)都被释放。图6-24给出了服务器端所经历的典型的状态序列,假设连接的终止是由客户发起的。其过渡过程在此就不多说了。在这两个状态过渡图中,我们仅仅给出了一个TCP连接通常是如何建立和终止的。我们没有描述在问题场景中会发生什么,例如,当连接的双方同时想终止连接时该如何。6.4.4TCP传输策略除了连通性和数据传输服务外,TCP也在尽力提高数据传输效率。在两台计算机间建立起了连接并不意味着具有平稳的、有效的数据传输。在数据传输过程中遇到的每个问题都引出了很多旨在提高效率的数据传输概念。比如滑动窗口、愚笨窗口综合症、Nagle算法和延迟确认等。1.滑动窗口在收到先前发送的数据段的确认后,计算机才开始传输下一段。这样的传输方法虽然安全,但有一个很大的缺点:在某一时刻,全双工连接两端的计算机在传输图6-24服务器端TCP状态序列下一数据段前需要闲置很长的时间去等待确认消息。尽管这种数据传输方法确保了数据的安全传输,但浪费了大量网络资源,所以权衡一下,还是弊大于利。为了提高现有框架中的效率,滑动窗口的概念应运而生。滑动窗口的概念很简单,它摈弃了一次只传输一个数据段的做法,而是将多个数据段放置到一个称为窗口的组中,并且其中所有的数据段都不需要等待确认消息,就可以作为一个整体发送出去。例如,如果一个窗口中包含了5个需要发送的数据段,所有5个数据段都将在同一时刻发送。在了解窗口是如何“滑动”前,首先必须知道窗口是如何设计的。所有未确认的数据段都位于窗口的左边,而那些能立即发送的数据段位于窗口的右边。当窗口中第一个数据段的确认消息到达后,窗口滑动到右边,将此数据段包含在窗口的右边。这样,滑动窗口确保了发送计算机能够传输更大数量的段。图6-25说明了滑动窗口概念是如何实现的。在图6-25中,数据段1和数据段2是由接收端发送和确认的数据段。数据段3和数据段4已经发送出去,但还在等待确认。数据段5、6和7是窗口序列中即将要发送的下一数据段。当位于窗口左端底部的数据段的确认消息到达后,数据段8和9就会被包括进窗口中。图6-25显示了窗口的滑动效应—窗口向前滑动,当经过确认的数据段3被释放出去后,数据段8就进入了窗口的右端。发送端同时传输多个数据段很好,但如果接收端不能容纳大量数据段的话,就会发生拥塞。因此,接收端必须根据自己所能接收和缓冲的数据大小,控制发送端计算机的窗口大小。为了通知发送端窗口的大小,接收端将在确认段TCP段头的窗口(Window)字段中指定窗口的大小。这个信息能让发送端根据接收端所需要的大小,调整自己的窗口尺寸。音乐播放软件是一个滑动窗口的典型例子,这种软件在播放音频文件前先缓冲已发送等待确认123456789需要立即发送已发送并确认123456789等待确认需要立即发送已发送并确认图6-25窗口滑动示意传入的数据。2.发送端愚笨窗口综合症早期TCP实现面临的问题之一是愚笨窗口综合症(SillyWindowSyndrome)。这种问题发生在发送端发送很大的段而阻塞了接收端缓冲区的时候。作为回应,接收端向外通告一个非常小的窗口尺寸,因为它的可用缓冲区已经急剧减小。于是发送端就发送非常小的数据段,这将导致网络资源利用率的严重低下。该问题可进一步分成两类:发送端愚笨窗口综合症和接收端愚笨窗口综合症。前者中发送端传输非常小的数据段,而后者中接收端通告很小的窗口尺寸。发送端愚笨窗口综合症也会发生在当发送端传输发送端应用所提供的小数据段时。为了解决这个问题,必须使用Nagle算法。这种算法是由JohnNagle发明的,最初用在福特汽车公司的TCP/IP专用网上。后来其他的TCP实现也采用了这种方法,因为它们也面临同样的问题。Nagle算法通过限制发送端一收到确认就立即传输数据。发送端不传输小数据段,而是将要发送的数据段积聚成一个大块的数据段。于是,如果收到确认时,累计的数据段在尺寸上接近MSS值,发送端就一下子传输所有数据段。这个方法目的在于通过传输更大的数据段,并给接收端以喘息之机,以便能在将这些数据段定向给所调用的应用之前清空自己的缓冲区,从而提高网络的利用率。在缓冲区的空间增大后,接收端就能通告一个更大的窗口尺寸。3.接收端愚笨窗口综合症接收端愚笨窗口综合症是通过在接收端计算机上应用一个与Nagle算法类似的概念来解决的。这个概念被称为延迟确认(DelayedAcknowledgements),它在收到发送端的数据段后,并不立即发送确认。这个延迟让接收端有时间清空自己超载的缓冲区。当缓冲区中有一半的空间后,一个表明所有数据段均已收到的确认就被发送出去。由于增大了缓冲区的空间,所以被通告的窗口尺寸也将大于在立即确认传输情况下的窗口尺寸。更大的窗口尺寸使得发送端能传输更大的数据段。当然过度的延迟确认会导致发送端重传段的副本。另外通过利用往返时间(RTT)计算而设置的重传定时器的值也会受影响,并导致估计错误的RTT。解决办法就是将延迟的最大时间设成推荐的500毫秒。6.4.5TCP拥塞控制基于信用量的TCP流控制机制是为了使目的端能够限制来自源端的报文流,以避免目的端缓存溢出。因特网的流控制技术也为源端与目的端之间提供拥塞控制。拥塞对数据传输的影响主要体现在两个方面:一方面是当拥塞开始出现时,报文流通过一个网络或互联网的时延会增加;另一方面是当拥塞变得严重时,网络或互联网的结点就要丢弃分组或报文段。TCP流控制机制可用于识别拥塞的发作,并以通过减少数据流量作出反应。但是,发送端的主机在发送数据时,既要考虑到接收端的接收能力,又要不使得网络发生拥塞。为此发送方维护两个窗口,一个是接受方准许的窗口,它是接受方给发送方预设的发送窗口大小;第二个是拥塞窗口(congestionwindow),它描述发送方在拥塞控制情况下一次最多能发送的数据包的数量,这是发送方根据自己估计的网络拥塞程度而设置的窗口的。每个窗口反映了发送方可以传送的字节数量。最终允许发送的字节数量是两个窗口的最小值。因此,发送窗口是“发送方认为没有问题的窗口”与“接收方认为没有问题的窗口”中较小的那个窗口。如果接收方说“可以发送8KB”,但是发送方知道,超过4KB的突发数据就会堵塞网络,那么,它就发送4KB。另一方面,如果接收方说“可以发送8KB”,而发送方知道,即使多达32KB的突发数据也可以很容易地通过网络,那么,它按照对方的要求发送完整的8KB数据。因此,控制发送窗口的大小至关重要。另外我们在讨论拥塞控制算法时,除了接收方窗口和拥塞窗口外,我们还要使用第三个参数:阈值(threshold),它是拥塞控制中慢启动阶段和拥塞避免阶段的分界点,它是影响拥塞窗口增长的变量,初始大小通常设置为65535字节。下面讨论两种在现代TCP实现中都要用到的技术—慢启动和拥塞避免。1.慢启动当一个连接被建立起来的时候,发送方将拥塞窗口初始化为该连接上当前使用的最大数据段长度。然后,它发送一个最大的数据段(1个MSS)。如果该数据段在定时器过期之前被确认,则它将拥塞窗口增加一个数据段的字节数,从而使拥塞窗口变成两倍的最大数据段长度,然后发送两个数据段(2个MSS)。如果这两个数据段中的每一个都被确认了,则拥塞窗口再增加两个最大数据段长度。当拥塞窗口达到n个数据段的时候,如果所有n个数据段都被及时确认的话,则拥塞窗口增加这n个数据段所对应的字节数,实际上,每一批被确认的突发数据段都会使拥塞窗口加倍。拥塞窗口一直呈指数增长,直至发生超时,或者达到接收方窗口的大小。这里的思想是,如果一定大小的突发数据,比如说1024、2048和4096字节,都被正常地传送过去,但是8192字节的突发数据却发生了超时,则拥塞窗口应该被设置为4096以避免拥塞。只要拥塞窗口保持在4096上,则无论接收方准许的窗口空间有多大,发送方都不会发送超过4096字节的突发数据。这个算法被称为慢启动算法,它是指数量级的,所有的TCP实现都要求支持该算法。2.拥塞避免当窗口的大小超过阈值的时候,慢启动阶段就结束了,一旦拥塞窗口大于当前的阈值,拥塞窗口的增长速度就由指数级增长变为线性增长,如果w是拥塞窗口的当前值,并且w比阈值要大,那么当w确认到达后,TCP就用w+1来替换w的值这就使得在每一次整个窗口确认到达所花费的所有来回程的时间里,拥塞窗口的大小都会增加1,算法的这个阶段被称为拥塞避免。只要确认在其相应的超时之前到达,拥塞避免阶段就会持续下去。但是窗口的大小以及TCP发送方可发送的数据速率不可能永远增加。最后,该TCP速率使得该路径上的一条链路变为饱和,这是将会发生丢失现象(这也就导致了发送方的超时)。当超时发生时,则按如下规则动态调整窗口大小。①设阈值为目前拥塞窗口的一半。②再设拥塞窗口=1个MSS,并执行慢启动过程,直到拥塞窗口=阈值。③当拥塞窗口≥阈值时,则每过一个传输往返时间就对拥塞窗口加1,使得拥塞窗口呈线性增长。TCP拥塞窗口的变化过程如图6-26所示。图6-26中,将阈值初始化为8MSS,拥塞窗口在慢启动阶段呈指数增长,并且在第三次发送时达到了阈值。从这时起在发生丢失之前,也就是在第7次传输之前,拥塞窗口以线性速度增长。注意当发生丢失的时候拥塞窗口大小为12MSS,阈值这时被设为拥塞窗口的一半,也就是6MSS,之后又开始该过程。该拥塞控制算法时由V.Jacobson[Jacobson1988]提出的。6.4.6TCP计时器管理TCP使用了多种计时器来完成它的工作,其中最重要的是重传计时器,还有持续计时器、保活计时器和关闭连接时的计时器。1.重传计时器为了控制丢失的或丢弃的数据段,TCP采用了重传计时器,用来计算确认到达123456789101112131415123456789101112131415阈值阈值发送次数拥塞窗口(单位:段)超时图6-26TCP拥塞窗口的变化时间,决定数据段是否需要重传及重传的时间。当TCP发送数据段时,它就创建该数据段的重传计时器。在这之后可能会有两种情况发生:如果在计时器超时时间到之前收到了对该数据段的确认,则撤消此计时器;如果计时器超时时间到仍然没有收到对该数据段的确认,那么TCP重传该数据段并将计时器复位。从计时器开始计时到终止之间的时间间隔称为计时器的超时时间(fimeout)。这里很自然地存在一个问题,超时时间应该为多长?显然,超时时间应该比连接的往返时间长,也就是说,从一个数据段被发送时起到确认收到之间的时间间隔。否则,就会出现多余的重发事件。但是超时时间又不能比往返时间大很多:否则,当一个数据段丢失了,TCP就不会很快地重发该数据段,这样就会给应用程序中引入较大的数据传输延迟。在详细地讨论超时时间间隔之前,让我们较深入地看一下往返时间(RTT)。以下的讨论就是基于[Jacobsonl988]中的TCP研究工作的。⑴对平均往返时间的估计一个数据段的RTT的采样(称为SRTT),就是从发送该数据段(即传送到IP)到该数据段的确认被接收之间的时间。每一个发送的数据段都有它自己的相关SRTT。很显然,每一个数据段的SRTT的值都是不同的,它们随着路由器的拥塞情况和终端系统的不同负载而变化。由于这种波动,给出的SRTT值可能是非典型的。为了估计一个典型的RTT,应该计算这些SRTT值的某个平均值。TCP会为这些SRTT值保留一个平均值,被称为ESRTT。当接收到一个确认并且得到一个新的SRTT的时候,TCP就会根据下面的公式修改ESRTT:ESRTT=(1-x)ESRTT+xSRTTESRTT的新值是以前的ESRTT值和新的SRTT的加权结合。x的一个典型值是x=0.125(即1/8),在这种情况下,以上的公式就变为:ESRTT=0.875ESRTT+0.125SRTT⑵设置超时时间超时值的设置应该使得计时器仅在很少的情况下发生过早超时(也就是说,在一个数据段的ACK的到达被延迟的时候)。这样,显然应该将超时值设为ESRTT和某个差值的和。当各个SRTT的值波动很大的时候,该差值会很大;当几乎没有波动的时候,该差值会很小。TCP使用以下的公式:Timeout(超时时间)=ESRTT+4Deviation这里偏差(Deviation)是对SRTT值与ESRTT值之间差值的估计:Deviation(偏差)=(1-x)Deviation+xSRTT-ESRTT注意,偏差是一个SRTT和ESRTT之间差值的指数加权移动平均值。如果SRTT的波动很小,那么偏差将会很小,而且超时时间几乎不比ESRTT大;如果波动很大,那么偏差将会很大,而且超时时间会比ESRTT大很多。2.持续计时器为了处理零窗口大小通知,TCP需要使用坚持计时器。假定接收端的TCP宣布了窗口大小为零。发送端的TCP就停止传送数据段,直到接收端的TCP发送确认并宣布一个非零的窗口。这个确认可能会丢失。如果确认报文段丢失,接收端的TCP就认为它已经完成任务,并等待着发送端的TCP发送更多的报文段。发送端的TCP由于没有收到确认,就等待对方发送确认来通知窗口的大小。这样,双方的TCP都在永远地等待着对方的通知状态,这就可能出现了死锁。为了避免出现死锁,TCP为每一个连接使用一个持续计时器。当发送端的TCP收到一个窗口大小为零的确认时,就需要启动持续计时器。当持续计时器期限到时,发送端的TCP就发送一个特殊的探测数据段。这个数据段只有1B的数据。探测数据段提醒接收端的TCP:确认已经丢失,必须重传。持续计时器的值一般与重传时间的数值相同。如果发送端没有收到从接收端来的响应,则需将持续计时器的值加倍和复位,并继续发送探测数据段。持续计时器值最大到门限值(通常是60s)。在这以后,发送端每隔60s就发送一个探测数据段,直到窗口重新打开。3.保活计时器保持计时器又叫做激活计时器,它是用来防止在两个TCP之间的连接处于长期空闲状态。如果客户建立了到服务器的连接,传送了一些数据,然后就停止了传送,可能这个客户端出现了故障。在这种情况下,这个连接将永远地处于打开状态。为了防止出现这类问题,服务器需要设置激活计时器。每当服务器收到客户的信息,就将计时器复位。如果服务器超过了激活计时器规定的时间,还没有收到客户的信息,它就每隔一个时间(如75s)发送一个探测数据段。如果发送了10个探测数据段还没有响应,就判断客户端出现故障,服务器将终止该连接。4.释放连接时的计时器释放连接时的定时器是在释放传输连接处于TIMEDWAIT状态中使用的计时器,它运行两倍的最大分组生存期时间,以确保连接被释放以后,该连接上所创建的所有的分组完全消失。小结传输层是计算机网络体系结构中非常重要的一层。传输层的作用是在源主机与目的主机进程之间提供端到端数据传输,而传输层以下各层只提供相邻结点之间的点对点数据传输,从“点对点”通信到“端到端”通信是一次质的飞跃。传输层协议可以提供给网络应用程序的服务。作为一个极端,传输层协议可以非常简单并且只给应用程序提供必要的服务,只为每一个通信中的进程提供多路复用/多路分解功能。另一个极端是,传输层协议可以给应用程序提供各种各样的保障,如数据的可靠传输、延迟保障和带宽保障。即使网络层是不可靠的,传输层协议仍然可以通过将确认、计时器、重发和顺序号这些因素仔细的结合起来,提供可靠数据传输。Internet传输层采用了TCP协议与UDP协议。TCP是一种面向连接的、可靠的传输层协议。TCP协议在IP服务的基础上,提供面向连接、可靠的流传输。UDP是一种无连接的、不可靠的传输层协议。习题六1.填空题(1)传输层的作用是在源主机与目的主机进程之间提供__________数据传输,而传输层以下各层只提供相邻结点之间的_____________数据传输。(2)若需要较高的吞吐量,传输层可以建立多条网络连接来支持一条传输连接,这就是_________。或者,为了节省费用,传输层也可以让多个传输通信合用一条网络连接,称为_________。(3)传输层通过传输服务原语向传输用户提供服务,取决于不同的系统,传输服务原语的表现(实现)形式可以有所不同,在Unix环境下通过__________形式来实现,在Windows环境下一般都通过______________来实现。(4)RPC借用了___________的概念,并且RPC模型提供了网络编程的抽象,利用这一模型,可以采用与本地过程调用类似的思想与概念来进行进程间的通信。(5)RTP为Internet上端到端的___________提供时间信息和流同步,但并不保证服务质量,服务质量由___________来提供。(6)TCP使用了多种计时器来完成它的工作,其中最重要的是_____________,还有_______________、______________和________________。2.选择题(1)UDP是一种_______协议;TCP是一种_______协议。A.传输B.网络C.无连接协议D.面向连接(2)TCP握手处理进程有几步_______。A.2步B.3步C.4步D.上面都不对(3)在OSI参考模型中,实现端到端的应答、分组排序和流量控制功能的协议层是______。A.数据链路层B.网络层C.传输层D.会话层(4)______是传输层数据交换的基本单位?A.比特B.分组C.帧D.报文段(5)UDP的头部有______字节。A.4字节B.8字节C.16字节D.32字节3.简答题(1)试问传输层的功能有什么?传输层的环境对传输协议将产生哪些影响?(2)传输层向上层提供的服务?(3)传输层建立连接时,Tomlinson(1975)引入了三次握手,为什么建立连接时需要第三次握手呢?(4)简述Internet上针对多媒体数据流的实时传输协议RTP与实时传输控制协议RTCP。(5)UDP是一种不可靠的网络协议,那么还有什么使用价值或必要呢?请举例说明,并介绍使用UDP的应用实例。(6)TCP为了提高数据传输效率都采用了那些策略?(7)TCP的拥塞控制中提到了最大段尺寸(MSS)和往返时间(RTT),简述它们的概念和应用。(8)简述TCP的拥塞控制算法。',)


  • 编号:1700775030
  • 分类:其他文档
  • 软件: wps,office word
  • 大小:60页
  • 格式:docx
  • 风格:商务
  • PPT页数:628224 KB
  • 标签:

广告位推荐

相关其他文档更多>