加入VIP
  • 专属下载特权
  • 现金文档折扣购买
  • VIP免费专区
  • 千万文档免费下载

上传资料

关闭

关闭

关闭

封号提示

内容

首页 TCP-IP详解卷3:TCP事务协议

TCP-IP详解卷3:TCP事务协议.pdf

TCP-IP详解卷3:TCP事务协议

老书不好找
2010-10-19 0人阅读 举报 0 0 暂无简介

简介:本文档为《TCP-IP详解卷3:TCP事务协议pdf》,可适用于IT/计算机领域

TCPIP详解卷:TCP事务协议我们愿意向广大的读者推荐WRichardStevens关于TCPIP的经典著作(共卷)的中译本。这里是其中的第卷:《TCPIP详解卷:TCP事务协议、HTTP、NNTP、UNIX域协议》。大家知道TCPIP已成为计算机网络的事实上的标准。在关于TCPIP的论著中最有影响的就是两部著作。一部是DouglasEComer的《用TCPIP进行网际互连》一套共卷(中译本已由电子工业出版社于年出版)而另一部就是Stevens写的这卷书。这两套巨著都很有名各有其特点。无论是从事计算机网络的教师还是进行科研的技术人员这两套书都应当是必读的。本书的特点是内容丰富概念清楚且准确讲解详细例子很多。作者在书中举出的所有例子均在作者安装的计算机网络上经过实际验证。在本书的最后作者给出了许多经典的参考文献并一一写出评注。第卷是第、卷的继续和深入。读者在学习这一卷时应当先具备第卷和第卷所阐述的、关于TCPIP的基本知识和实现知识。本卷仍然采用了大量的源代码来讲述协议及其应用的实现并且本卷使用的一部分源代码是对第卷和第卷中有关源代码的修改需要对照参考。这些内容对于编写TCPIP网络应用程序的程序员和研究TCPIP的计算机网络研究人员是非常有用的。本卷书的前言由胡谷雨翻译第~章由胡谷雨、马春华翻译第~章由胡谷雨、张晖翻译第~章由吴礼发、李旺翻译第~章由吴礼发、金风林翻译附录由胡谷雨翻译。全书由谢希仁进行校阅。限于水平翻译中不妥或错误之处在所难免敬请广大读者批评指正。译者年月于解放军理工大学南京下载引言和本书的组织:本书是“TCPIP详解系列”的延续:此系列的卷是Stevens卷是WrightandStevens。本书分成三个部分每个部分覆盖了不同的内容。()TCP事务协议通常叫做TTCP。这是对TCP的扩展其设计目的是使客户服务器事务更快、更高效和更可靠。这个目标的实现省略了连接开始时TCP的三次握手并缩短了连接结束时TIMEWAIT状态的持续时间。我们将会看到在客户服务器事务中TTCP的性能与UDP相当而且TTCP具有可靠性和适应性这两点相对UDP来说都是很大的改进。事务是这样定义的:一个客户向服务器发出请求接下来是服务器给出响应(这里的名词“事务”(transaction)并非数据库中的事务处理数据库中的事务处理有封锁、两步提交和回退)。()TCPIP应用特别是HTTP(超文本传送协议WWW的基础)和NNTP(网络新闻传送协议Usenet新闻系统的基础)。()Unix域协议。这些协议是所有Unix中的TCPIP实现中都提供的在许多非Unix的实现中也都提供。这些协议提供了进程之间通信(IPC)的一种手段采用了与TCPIP中一样的插口接口。当客户与服务器进程在同一主机上时Unix域协议通常要比TCPIP快一倍。第一部分即对TTCP的介绍又分成两个小部分。第~章介绍协议并给出了大量实例来说明它们是怎样工作的。这些材料主要是对卷中节的补充在那里对TTCP只是做了简单的介绍。第小部分即第~章介绍TTCP在BSDLite网络代码(即卷中给出的代码)中的确切实现。由于最早的TTCP实现迟至年月才发布已经是本书卷出版一年以后了那时卷也快完成了因此TTCP的详细叙述包括诸多实例和所有的实现细节都只好放在本系列书的卷中了。第二部分即HTTP和NNTP应用是卷的第~章中介绍TCPIP应用的延续。在卷出版后的两年里随着Internet的发展HTTP得到了极大的流行而NNTP的使用则在最近的多年中每年增长了大约。TTCP对HTTP来说也是非常好的可以这样来用TCP:在少量数据传输中缩短连接时间因为这种时候连接的建立和拆除时间往往占总时间的大头。在繁忙的Web服务器上成千上万个不同而且不断变化的客户对HTTP(因此也对TCP)的高负荷使用也提供了唯一可以对服务器上确切的分组进行考查的机会(第章)可以观察卷和卷中给出的TCPIP的许多特性。第三部分中的Unix域协议原本是准备在卷中介绍的但由于卷已多达页而删去了。在书名为《TCPIP详解》这样的系列书中夹杂着TCPIP以外的协议不免令人生奇但Unix域协议几乎年前就已经伴随着BSD版TCPIP的实现在BSD中发布了。今天它们在任何一个从伯克利衍生而来的内核中都在频繁地使用但它们的使用往往“被掩盖在后台”大多数用户不知道它们的存在。除了在从伯克利衍生而来的内核中充当Unix管道的基础外它们的另一个大用户是当客户程序和服务器程序在同一主机(典型的情况是工作站)上时的XWindow系统。Unix域的插口也用于进程之间传递描述符也是进程之间通信的一个强大工具。由于Unix域协议所用的插口API(应用编程接口)与TCPIP所用的插口API几乎是相同的Unix域协议以最小的代码变化提供了一个简单的手段来增强本地应用的性能。以上三个部分的每个部分都可以独立阅读。读者:与本系列书的前两卷一样这一卷是为所有想要理解TCPIP如何工作的人写的:编写网络应用的程序员负责维护采用TCPIP的计算机和网络的系统管理员以及在日常工作中经常与TCPIP应用程序打交道的用户。第一和第二部分是理解TCPIP工作原理的基础。不熟悉TCPIP的读者应该看看本系列书的卷见Stevens以便对TCPIP协议集有一个全面的了解。第一部分的前半部分(第~章TCPIP中的概念和例子)与卷无关可以直接阅读。但后半部分(第~章TTCP的实现)则需要先熟悉BSDLite网络程序这些内容在卷中介绍。在整本书中有大量的向前和向后参考索引这些参考索引是针对本书的两个主题以及对卷和卷的内容为想要了解更详细内容的读者提供的。在本书最后有书中用到的所有缩略语封底背面则有书中介绍的所有结构、函数和宏(以字母顺序排列)及其介绍起始页码的交叉参考列表。如果本书引用了卷中的定义则该交叉参考列表也列出了卷中的定义。源码版权:本书中引自BSDLite版的所有源码(源程序)都包括有下面这样的版权说明:(略)第章路由表的源码则包括下面这样的版权说明:(略)印刷惯例:当需要显示交互的输入和输出信息时将用黑体表示键盘输入而计算机输出则用Courrier体并用中文宋体作注释。书中总是把系统名作为命令解释程序提示符的一部分(例如sun)以说明命令是在哪个主机上执行的。在正文中引用的程序名通常都是首字母大写(如Telnet和Tcpdump)以避免过多的字体形式。在整个这本书中我们将用像上述这段文字一样的缩进、附加的注释来说明实现细节中的历史阶段。书中难免会有错误希望读者和专家提出宝贵意见以帮助我们进一步完善。WRichardStevensTucson,Arizona年月rstevensnoaoeduhttp:wwwnoaoedu~rstevens目录第一部分TCP事务协议第章TTCP概述概述UDP上的客户服务器TCP上的客户服务器TTCP上的客户服务器测试网络时间测量程序应用历史实现小结第章TTCP协议概述TTCP中的新TCP选项TTCP实现所需变量状态变迁图TTCP的扩展状态小结第章TTCP使用举例概述客户重新启动常规的TTCP事务服务器收到过时的重复SYN服务器重启动请求或应答超出报文段最大长度MSS向后兼容性小结第章TTCP协议(续)概述客户的端口号和TIMEWAIT状态设置TIMEWAIT状态的目的TIMEWAIT状态的截断利用TAO跳过三次握手小结第章TTCP协议的实现:插口层概述常量sosend函数小结第章TTCP的实现:路由表概述代码介绍radixnodehead结构rtentry结构rtmetrics结构ininithead函数inaddroute函数inmatroute函数inclsroute函数inrtqtimo函数inrtqkill函数小结第章TTCP实现:协议控制块概述inpcbladdr函数inpcbconnect函数小结第章TTCP实现:TCP概要概述代码介绍TCP的protosw结构TCP控制块tcpinit函数tcpslowtimo函数小结第章TTCP实现:TCP输出概述tcpoutput函数新的自动变量增加隐藏的状态标志在SYNSENT状态不要重传SYN发送器的糊涂窗口避免机制有RST或SYN标志时强制发送报文段发送MSS选项是否发送时间戳选项发送TTCP的CC选项根据TCP选项调整数据长度小结第章TTCP实现:TCP函数概述tcpnewtcpcb函数tcprtlookup函数tcpgettaocache函数重传超时间隔的计算tcpclose函数tcpmsssend函数tcpmssrcvd函数tcpdooptions函数tcpreass函数小结第章TTCP实现:TCP输入概述预处理首部预测被动打开的启动主动打开的启动PAWS:防止序号重复ACK处理完成被动打开和同时打开ACK处理(续)FIN处理小结第章TTCP实现:TCP用户请求概述PRUCONNECT请求tcpconnect函数PRUSEND和PRUSENDEOF请求tcpusrclosed函数tcpsysctl函数TTCP的前景小结第二部分TCP的其他应用第章HTTP:超文本传送协议概述HTTP和HTML概述HTTP报文类型:请求与响应首部字段响应代码各种报文头举例例子:客户程序缓存例子:服务器重定向一个例子HTTP的统计资料性能问题小结第章在HTTP服务器上找到的分组概述多个HTTP服务器客户端SYN的到达间隔时间RTT的测量用listen设置入连接队列的容量客户端的SYN选项客户端的SYN重传域名超时的持续探测TTCP路由表大小的模拟mbuf的交互TCP的PCB高速缓存和首部预测小结第章NNTP:网络新闻传送协议概述NNTP一个简单的新闻客户一个复杂的新闻客户NNTP的统计资料小结第三部分Unix域协议第章Unix域协议:概述概述用途性能编码举例小结第章Unix域协议:实现概述代码介绍Unixdomain和protosw结构Unix域插口地址结构Unix域协议控制块uipcusrreq函数PRUATTACH请求和unpattach函数PRUDETACH请求和unpdetach函数PRUBIND请求和unpbind函数PRUCONNECT请求和unpconnect函数PRUCONNECT请求和unpconnect函数socketpair系统调用pipe系统调用PRUACCEPT请求PRUDISCONNECT请求和unpdisconnect函数PRUSHUTDOWN请求和unpshutdown函数PRUABORT请求和unpdrop函数其他各种请求小结第章Unix域协议:IO和描述符的传递概述PRUSEND和PRURCVD请求描述符的传递unpinternalize函数unpexternalize函数unpdiscard函数unpdispose函数unpscan函数unpgc函数unpmark函数性能(再讨论)小结附录A测量网络时间附录B编写TTCP应用程序参考文献缩略语下载下载第章TTCP概述概述本章首先介绍客户服务器事务概念。我们从使用UDP的客户服务器应用开始这是最简单的情形。接着我们编写使用TCP的客户和服务器程序并由此考察两台主机间交互的TCPIP分组。然后我们使用TTCP证明利用TTCP可以减少分组数并给出为利用TTCP需要对两端的源代码所做的最少改动。接下来介绍了运行书中示例程序的测试网络并对分别使用UDP、TCP和TTCP的客户服务器应用程序进行了简单的时间耗费比较。我们考察了一些使用TCP的典型Internet应用程序看看如果两端都支持TTCP将需要做哪些修改。紧接着简要介绍了Internet协议族中事务协议的发展历史概略叙述了现有的TTCP实现。本书全文以及有关TTCP的文献中事务一词的含义都是指客户向服务器发出一个请求然后服务器对该请求作出应答。Internet中最常见的一个例子是客户向域名服务器(DNS)发出请求查询域名对应的IP地址然后域名服务器给出响应。本书中的事务这个术语并没有数据库中的事务那样的含义:加锁、两步提交、回退等等。UDP上的客户服务器我们先来看一个简单的UDP客户服务器应用程序的例子其客户程序源代码如图所示。在这个例子中客户向服务器发出一个请求服务器处理该请求然后发回一个应答。图UDP上的简单客户程序第一部分TCP事务协议图(续)本书中所有源代码的格式都是这样。每一非空行前面都标有行号。正文中叙述某段源代码时这段源代码的起始和结束行号标记于正文段落的左边如下面的正文所示。有时这些段落前面会有一小段说明对所描述的源代码进行概要说明。源代码段开头和结尾处的水平线标明源代码段所在的文件名。这些文件名通常都是指我们在节中将介绍的版BSDLite中发布的文件。我们来讨论这个程序的一些有关特性但不详细描述插口函数因为我们假设读者对这些函数有一些基本的认识。关于插口函数的细节在参考书Stevens的第章中可以找到。图给出了头文件cliservh。创建UDP插口socket函数用于创建一个UDP插口并将一个非负的插口描述符返回给调用进程。出错处理函数errsys参见参考书Stevens的附录B。这个函数可以接受任意数目的参数但要用vsprintf函数对它们格式化然后这个函数会打印出系统调用所返回的errno值所对应的Unix出错信息然后终止进程。填写服务器地址首先用memset函数将Internet插口地址结构清零然后填入服务器的IP地址和端口号。为简明起见我们要求用户在程序运行中通过命令行输入一个点分十进制数形式的IP地址(argv)。服务器端口号(UDPSERVPORT)在头文件cliservh中用#define定义在本章的所有程序首部中都包含了该头文件。这样做是为了使程序简洁并避免使调用gethostbyname和getservbyname函数的源代码复杂化。构造并向服务器发送请求客户程序构造一个请求(只用一行注释来表示)并用sendto函数将其发出这样就有一个UDP数据报发往服务器。同样是为了简明起见我们假设请求(REQUEST)和应答(REPLY)的报文长度为固定值。实用的程序应当按照请求和应答的最大长度来分配缓存空间但实际的请求和应答报文长度是变化的而且一般都比较小。读取和处理服务器的应答调用recvfrom函数将使进程阻塞(即置为睡眠状态)直至收到一个数据报。接着客户进程处理应答(用一行注释来表示)然后进程终止。由于recvfrom函数中没有超时机制请求报文或应答报文中任何一个丢失都将造成该进程永久挂起。事实上UDP客户服务器应用的一个基本问题就是对现实世界中的此类错误缺少健壮性。在本节的末尾将对这个问题做更详细的讨论。计计第一部分TCP事务协议下载在头文件cliservh中我们将SA定义为structsockaddr*即指向一般的插口地址结构的指针。每当有一个插口函数需要一个指向插口地址结构的指针时该指针必须被置为指向一个一般性插口地址结构的指针。这是由于插口函数先于ANSIC标准出现在年代早期开发插口函数的时候void*(空类型)指针类型尚不可用。问题是“structsockaddr*”总共有个字符这经常使这一行源代码超出屏幕(或书本页面)的右边界因此我们将其缩写成为SA。这个缩写是从BSD内核源代码中借用过来的。图给出了在本章所有程序中都包含的头文件cliservh。图本章各程序中均包含的头文件cliservh图给出了相应的UDP服务器程序。图与图的UDP客户程序对应的UDP服务器程序第章TTCP概述计计下载图(续)创建UDP插口和绑定本机地址调用socket函数创建一个UDP插口并在其Internet插口地址结构中填入服务器的本机地址。这里本机地址设置为通配符(INADDRANY)这意味着服务器可以从任何一个本机接口接收数据报(假设服务器是多宿主的即可以有多个网络接口)。端口号设为服务器的知名端口(UDPSERVPORT)该常量也在前面讲过的头文件cliservh中定义。本机IP地址和知名端口用bind函数绑定到插口上。处理客户请求接下来服务器程序就进入一个无限循环:等待客户程序的请求到达(recvfrom)处理该请求(我们只用一行注释来表示处理动作)然后发出应答(sendto)。这只是最简单的UDP客户服务器应用。实际中常见的例子是域名服务系统(DNS)。DNS客户(称作解析器)通常是一般客户应用程序(例如Telnet客户、FTP客户或WWW浏览器)的一个部分。解析器向DNS服务器发出一个UDP数据报查询某一域名对应的IP地址。服务器发回的应答通常也是一个UDP数据报。如果观察客户向服务器发送请求时双方交换的分组我们就会得到图这样的时间系列页面上时间自上而下递增。服务器程序先启动其行为过程给在图的右半部客户程序稍后启动。我们分别来看客户和服务器程序中调用的函数及其相应内核执行的动作。在对socket函数的两次调用中上下紧挨着的两个箭头表示内核执行请求的动作并立即返回。在调用sendto函数时尽管内核也立即返回但实际上已经发出了一个UDP数据报。为简明起见我们假设客户程序的请求和服务器程序的应答所生成的IP数据报的长度都小于网络的最大传输单元(MTU)IP数据报不必分段。在这个图中有两次调用recvfrom函数使进程睡眠直到有数据报到达才被唤醒。我们把内核中相应的例程记为sleep和wakeup。最后我们还在图中标出了事务所耗费的时间。图的左侧标示的是客户端测得的事务时间:从客户发出请求到收到服务器的应答所经历的时间。组成这段事务时间的数值标在图的右侧:RTTSPT其中RTT是网络往返时间SPT是服务器处理客户请求的时间。UDP客户服务器事务的最短时间就是RTTSPT。计计第一部分TCP事务协议下载图UDP客户服务器事务的时序图尽管没有明确说明但我们已经假设从客户到服务器的路径需要RTT时间返回的路径又需RTT时间。但实际情况并非总是如此。据对大约条Internet路径的研究Paxsonb发现:的路径呈现明显的不对称性说明两个方向上的路由经过了不同的站点。我们的UDP客户服务器看起来非常简捷(每个程序只有大约行有关网络的源代码)但在实际环境中应用还不够健壮。由于UDP是不保证可靠的协议数据报可能会丢失、失序或重复因此实用的应用程序必须处理这些问题。这通常是在客户程序调用recvfrom时设置一个超时定时器用以检测数据报的丢失并重传请求。如果要使用超时定时器客户程序就要测量RTT并动态更新这是因为互连网上的RTT会在很大范围内变化并且变化很快。但如果是服务器的应答丢失而不是请求那么服务器就要再次处理同一个请求这可能会给某些服务带来问题。解决这个问题的办法之一是让服务器将每个客户最近一次请求的响应暂存起来必要时重传这个应答即可而不需要再次处理这个请求。最后典型的情况是客户向服务器发送的每个请求中都有一个不同的标识服务器把这个标识在响应中传回来使客户能把请求和响应匹配起来。在参考书Stevens的节中给出了UDP上的客户服务器处理这些问题的源代码细节但这将在程序中增加大约行源代码。一方面许多UDP应用程序都通过执行所有这些额外步骤(超时机制、RTT值测量、请求标识等等)来增加可靠性另一方面随着新的UDP应用程序不断出现这些步骤也在不断地推陈出新。参考书Patridgeb中指出“为了开发‘可靠的UDP应用程序’你要有状态信息(序列号、重传计数器和往返时间估计器)原则上你要用到当前TCP连接块中的全部信第章TTCP概述计计下载客户端函数内核网络内核服务器端函数返回进程请求返回息。因此构筑一个‘可靠的UDP’本质上和开发TCP一样难”。有些应用程序并不实现上面所述的所有步骤:例如在接收时使用超时机制但并不测量RTT值当然更不会动态地更新RTT值。这样当应用程序从一个环境(比如局域网)移植到另一个环境(比如广域网)中应用时就可能会引发一些问题。比较好的解决办法是用TCP而不是用UDP这样就可以利用TCP提供的所有可靠传输特性。但是这种办法会使客户端测得的事务时间由RTTSPT增加到×RTTSPT(见下一节)而且还会大大增加两个系统之间交换的分组数目。对付这些新的问题也有一个办法即用TTCP取代TCP我们将在节中对此进行讨论。TCP上的客户服务器下一个例子是TCP上的客户服务器事务应用。图给出了客户程序。图TCP事务的客户创建TCP插口和连接到服务器调用socket函数创建一个TCP插口然后在Internet插口地址结构中填入服务器的IP地址和端口号。对connect函数的调用启动TCP的三次握手过程在客户和服务器之间建立起连接。卷的第章给出了TCP连接建立和释放过程中交换分组的详细情况。发送请求和半关闭连接客户的请求是用write函数发给服务器的。之后客户调用shutdown函数(函数的第计计第一部分TCP事务协议下载个参数为)关闭连接的一半即数据流从客户向服务器的方向。这就告知服务器客户的数据已经发完了:从客户端向服务器传递了一个文件结束的通知。这时有一个设置了FIN标志的TCP报文段发给服务器。客户此时仍然能够从连接中读取数据只关闭了一个方向的数据流。这就叫做TCP的半关闭(halfclose)。卷的第节给出了有关细节。读取应答读取应答是由函数readstream完成的如图所示。由于TCP是一个面向字节流的协议没有任何形式的记录定界符因而从服务器端TCP传回的应答可能会包含在多个TCP报文段中。这也就可能会需要多次调用read函数才能传递给客户进程。而且我们知道当服务器发送完应答后就会关闭连接使得TCP向客户端发送一个带FIN的报文段在read函数中返回一个文件结束标志(返回值为)。为了处理这些细节问题在readstream函数中不断调用read函数直到接收缓存满或者read函数返回一个文件结束标志。readstream函数的返回值就是读取到的字节数。图readstream函数还有一些别的方法可以在类似TCP这样的流协议中用来给记录定界。许多Internet应用程序(FTP、SMTP、HTTP和NNTP)使用回车和换行符来标记记录的结束。其他一些应用程序(DNSRPC)则在每个记录的前面加上一个定长的记录长度字段。在我们的例子中利用了TCP的文件结束标志(FIN)因为在每次事务中客户只向服务器发送一个请求而服务器也只发回一个应答。FTP也在其数据连接中采用了这项技术用以告知对方文件已经结束。图给出的是TCP的服务器程序。图TCP事务的服务器程序第章TTCP概述计计下载图(续)创建监听用TCP插口用于创建一个TCP插口并将服务器的知名端口绑定到该插口上。与UDP服务器一样TCP服务器也将通配符作为其IP地址。调用listen函数将新创建的插口作为监听插口用于等待客户端发起的连接。listen函数的第二个参数规定了允许的最大挂起连接数内核要为该插口将这些连接进行排队处理。SOMAXCONN在头文件<syssocketh>中定义。其数值过去一直都取但现在有一些比较新的系统将其定为。对于一些很繁忙的服务器(例如:Web服务器)已经发现需要取更大的值比如或。在节中我们还将对此问题进行更多的讨论。接受连接和处理请求服务器进程调用accept函数后就进入阻塞状态直到有客户进程调用connect函数而建立起一个连接。函数accept返回一个新的插口描述符sockfd代表与客户和服务器之间所建立的连接。服务器调用函数readstream读取客户的请求(图)再调用write函数向客户发送应答。这是一个反复循环的服务器:把当前的客户请求处理完毕后才又调用accept去接受另一个客户的连接。并发服务器可以并行地处理多个客户请求(即:同时处理)。在Unix的主机上实现并发服务器的常用技术是:在accept函数返回后调用Unix的fork函数创建一个子进程由子进程处理客户的请求父进程则紧接着又调用accept去接受别的客户连接。实现并发服务器的另一项技术是为每个新建立的连接计计第一部分TCP事务协议下载创建一个线程(叫做轻量进程)。为了避免那些与网络无关的进程控制函数把我们的例子搞复杂我们只给出了反复循环的服务器。参考书Stevens的第章讨论比较了循环服务器和并发服务器。还有第三个选择是采用预分支服务器。即服务器启动时连续调用fork函数数次并让每个子进程都在同一个监听插口描述符上调用accept函数。这种办法节省了为每个客户的连接请求临时创建子进程的时间开销这对于繁忙的服务器来说是很大的节省。有些HTTP服务器就采用了这项技术。图给出了TCP上客户服务器事务的时间系列。我们首先注意到与图中UDP上的第章TTCP概述计计下载客户端函数内核网络内核函数服务器端返回(数据)返回返回(数据)进程请求图TCP上客户服务器事务的时序事务相比网络上交换的分组数增加了:TCP上事务的分组数是而UDP上的则是。采用TCP后客户端测量的事务时间是不少于×RTTSPT。通常中间三个从客户到服务器的报文段(对服务器SYN的ACK、请求以及客户的FIN)是紧密相连的后面两个从服务器到客户的报文段(服务器的应答和FIN)也是紧密相连的。这使实际事务时间比从图中看到的更接近×RTTSPT。本例中多出来的一个RTT源于TCP连接建立的时间开销:图中前两个报文段所花的时间。如果TCP可以把建连和发送客户数据以及客户FIN(图中客户端发出的前四个报文段)合起来再把服务器的应答和FIN合起来事务时间就又可以回到RTTSPT了这与UDP的一样。事实上这就是TTCP中采用的基本技巧。TCP的TIMEWAIT状态TCP要求首先发出FIN的一端(我们的例子中是客户)在通信双方都完全关闭连接之后仍然要保持在TIMEWAIT状态直至两倍的报文段最大生存时间(MSL)。MSL的建议值是秒也即处于TIMEWATE状态要达到分钟。当连接处于TIMEWAIT状态时同一连接(即客户IP地址和端口号以及服务器IP地址和端口号这个值相同)不能重复打开(我们在第章中还要更多地讨论TIMEWAIT状态)。许多基于伯克利代码的TCP实现在TIMEWAIT状态的保持时间仅仅为秒而不是RFCBraden中指定的秒。在本书的所有计算中我们还是假定正确的等待周期为秒。在我们的例子中客户端首先发出FIN这称为主动关闭因而TIMEWAIT状态出现在客户端。在这个状态延续期内TCP要为这个已经关闭的连接保留一定的状态信息以便能正确处理那些在网络中延迟一段时间、在连接关闭之后到达的报文段。同样如果最后一个ACK丢失了服务器将重传FIN使客户端重传最后的ACK。其他一些应用程序特别是WWW中的HTTP要求客户程序发送一个专门的命令来指示已经将请求发送完毕(而不是像我们的客户程序那样采用半关闭连接的办法)接着服务器就发回应答紧接着就是服务器的FIN。然后客户程序再发出FIN。这样做与前面所述的不同之处在于现在的TIMEWAIT状态出现在服务器端而不是客户端。对许多客户访问的繁忙服务器来说需要保留的状态信息会占用服务器的大量内存。因此当设计一个事务性客户服务器应用程序时让连接的哪一端关闭后进入TIMEWAIT状态值得仔细斟酌。我们还将看到TTCP可以让TIMEWAIT状态的延续时间从秒减少到大约秒。减少TCP中的报文段数像图所示的那样把数据和控制报文段合并起来可以减少图中所示的TCP报文段数。请注意这里的第一个报文段中包含有SYN、数据和FIN而不像图中那样仅仅是SYN。类似地服务器的应答和服务器的FIN也可以合并。虽然这样的分组序列也符合TCP的规定但是作者无法在应用程序中利用现有的插口API使TCP产生这样的报文段序列(因此才在图中客户端产生第一个报文段时和服务器端产生最后一个报文段时标上了问号)而且据作者所知也没有哪一个应用程序确实生成了这样的报文段序列。值得一提的是尽管我们把报文段的数目由减少到了但客户端观测的事务依然是×RTTSPT。这是因为TCP中规定服务器端的TCP在三次握手结束之前不能向服务器进程提交数据(卷的第节说明了TCP是如何在连接建立之前将到达的数据进行排队缓存的)。加计计第一部分TCP事务协议下载上这种限制的原因是服务器必须确信来自客户的SYN是“新的”即不是以前某次连接的SYN在网络中延迟一段时间后到达服务器端的。确认过程是这样的:服务器对客户发送的SYN发送确认再发出自己的SYN然后等待客户对该SYN的确认。当三次握手完成之后通信双方就都知道对方的SYN是新的。由于在三次握手结束之前服务器无法开始处理客户的请求故分组数的减少并没有缩短客户端测得的事务时间。下面这段话引自RFCJacobson,Braden,andZhang的附录:“注意:使连接能够尽快重复利用是早期TCP开发的重要目标。之所以有这样的要求是因为当第章TTCP概述计计下载返回(数据)图最少TCP事务的时序将数据加入队列返回(数据)函数内核服务器端网络函数客户端内核进程请求时人们希望TCP既是应用层事务协议的基础同时也是面向连接协议的基础。当时讨论中甚至把既包含有SYN和FIN比特同时又包含数据的报文段叫做‘圣诞树’报文段和‘Kamikaze(敢死队)’报文段。但这种热情很快被泼了冷水因为人们发现三次SYN握手和FIN握手意味着一次数据交换至少需要个分组。而且TIMEWAIT状态的延续说明同一个连接不可能马上再次打开。于是再没有人在这个领域做进一步的研究尽管现在的某些应用程序(比如简单邮件传送协议SMTP)经常会产生很短的会话。人们一般都可以采用为每个连接选用不同的端口对的办法来避开重用问题”。RFCBradenb中写到:“这些‘Kamikaze(敢死队)’报文段不是作为一种支持的服务来提供而主要用来搞垮其他实验性的TCP!”作为一个实验作者编写了一个测试程序这个程序把SYN与数据和FIN在一个报文段中发出去即图中的第一个报文段。该报文段发给个不同版本Unix的标准echo服务器(卷的第节)再用Tcpdump观察所交换的数据。其中的个(BSD、AIX、BSDOS、HPUX、IRIXSystemV、SunOS和SystemVRelease)都能正确处理该报文段另外一个(Solaris)则把随SYN一起传送的数据扔掉迫使客户程序重传数据。那个系统中的报文段序列与图所描绘的不尽相同。当三次握手结束后服务器立刻就对客户的数据和FIN发出确认。另外由于echo服务器无法把数据和FIN捆绑在一起(图中的第四个报文段)发送结果是发了两个报文段而不只是一个:应答和紧接其后的FIN。因此报文段的总数是而不是图中所示的。我们在节中会进一步讨论与非TTCP实现的兼容性问题并给出一些Tcpdump的输出结果。许多从伯克利演变而来的系统中服务器无法处理接收到的报文段中只有SYN、FIN而没有数据、ACK的情况。这个bug使得新创建的插口保持在CLOSEWAIT状态直到主机重新启动。但这却是一个合法的TTCP报文段:客户建立起了一个连接没有发送任何数据然后就关闭连接。TTCP上的客户服务器我们的TTCP客户服务器的源代码和上一节的TCP客户服务器的源代码略有不同以便能够利用TTCP的优势。图给出了TTCP上的客户程序。图TTCP上的事务客户程序计计第一部分TCP事务协议下载图(续)创建TCP插口对socket函数的调用与TCP上的客户程序一样在Internet插口地址结构中同样也填入服务器的IP地址和端口号。向服务器发送请求TTCP上的客户程序不调用connect函数。而是直接调用标准的sendto函数该函数向服务器发送请求同时与服务器建立起连接。此外我们还用sendto函数的第个参数指定了一个新的标志MSGEOF用以告诉系统内核数据已经发送完毕。这样做就相当于图中调用shutdown函数向服务器发送一个FIN。MSGEOF标志是TTCP实现中新加入的不要把它与MSGEOR标志混淆后者是基于记录的协议(比如OSI的运输层协议)中用来标志记录结束的。我们将在图中看到调用sendto函数的结果是客户端的SYN、客户的请求以及FIN都包含在一个报文段中发送出去。换言之调用一个sendto函数就实现了connect、write和shutdown三个函数的功能。读服务器的应答读服务器的应答还是用readstream函数与前文讨论过的TCP上的客户程序一样。图所示的是TTCP上的服务器程序。图TTCP上的事务服务器程序第章TTCP概述计计下载图(续)这个程序与图中TCP上的服务器程序几乎完全一样:对socket函数、bind函数、listen函数、accept函数和readstream函数的调用都一模一样。唯一的不同在于TTCP上的服务器发送应答时调用的是send函数而不是write函数。这样就可以设置MSGEOF标志从而可以将服务器的应答和服务器的FI

用户评价(0)

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

文档小程序码

使用微信“扫一扫”扫码寻找文档

1

打开微信

2

扫描小程序码

3

发布寻找信息

4

等待寻找结果

我知道了
评分:

/49

TCP-IP详解卷3:TCP事务协议

仅供在线阅读

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利