TCP/IP详解(一)
1.12 标准的简单服务
有一些标准的简单服务几乎每种实现都要提供。在本书中我们将使用其中的一些服务程序,而客户程序通常选择Telnet。图1.9描述了这些服务。从该图我们可以看出,当使用TCP和UDP提供相同的服务时,一般选择相同的端口号.
(下面是原书p.15①的译文)
如果仔细检查这些标准的简单服务以及其他标准的TCP/IP服务(如Telnet, FTP, SMTP等)的端口号时,我们发现它们都是奇数。这是有历史原因的,因为这些端口号都是从NCP端口号派生出来的。(NCP,即网络控制协议,是ARPANET的运输层协议,是TCP的前身。NCP是单工的,不是全双工的,因此每个应用程序需要两个连接,需预留一对奇数和偶数端口号。当TCP和UDP成为标准的运输层协议时,每个应用程序只需要一个端口号,因此就使用了NCP中的奇数。
(以下是原书p.16图1.9的译文)
名字
TCP端口号
UDP端口号
RFC
描述
echo
7
7
862
服务器返回客户发送的所有内容。
discard
9
9
863
服务器丢弃客户发送的所有内容。
daytime
13
13
867
服务器以可读形式返回时间和日期。
chargen
19
19
864
当客户发送一个数据报时,TCP服务器发送一串连续的字符流,直到客户中断连接。UDP服务器发送一个随机长度的数据报。
time
37
37
868
服务器返回一个二进制形式的32 bit数,表示从UTC时间1900年1月1日午夜至今的秒数。
图1.9 大多数实现都提供的标准的简单服务
1.13 互连网
在图1.3中,我们列举了一个由两个网络组成的互连网-一个以太网和一个令牌环网。在1.4节和1.9节中,我们讨论了世界范围内的互连网-Internet,以及集中分配IP地址的需要(InterNIC),还讨论了著名的端口号(IANA)。internet这个词第一个字母是否大写决定了它具有不同的含义。
internet意思是用一个共同的协议族把多个网络连接在一起。而Internet指的是世界范围内通过TCP/IP互相通信的所有主机集合(超过100万台)。Internet是一个internet(互连网),但internet不等于Internet。
1.14 实现
既成事实标准的TCP/IP软件实现来自于位于伯克利的加利福尼亚大学的计算机系统研究小组。从历史上看,软件是随同4.x BSD系统(Berkeley Software Distribution)的网络版一起发布的。它的源代码是许多其他实现的基础。
图1.10列举了各种BSD版本发布的时间,并标注了重要的TCP/IP特性。列在左边的BSD网络版,其所有的网络源代码可以公开得到:包括协议本身以及许多应用程序和工具(如Telnet和FTP)。
在本书中,我们将使用“伯克利派生系统”来指SunOS 4.x, SVR4, 以及AIX 3.2等那些基于伯克利源代码开发的系统。这些系统有很多共同之处,经常包含相同的错误。
(以下是原书p.17图1.10的译文)
4.2BSD (1983) 第一个广泛可用的TCP/IP发布
4.3BSD (1986) TCP性能得到改善
4.3BSD Tahoe (1988) 启动慢,拥塞避免措施
BSD网络软件1.0版(1989):Net/1
4.3BSD Reno(1990) TCP首部预测,SLIP首部压缩
路由表修改
BSD网络软件2.0版(1991):Net/2
4.4BSD(1993) 多播,长胖管道修改
4.4BSD-Lite (1994)
又称为Net/3
图1.10 不同的BSD版及其重要的TCP/IP特性
起初关于Internet的很多研究现在仍然在伯克利系统中应用-新的拥塞控制算法(21.7节),多目传送(12.4节),“又长又胖的管道”修改(24.3节),以及其他类似的研究。
1.15 应用编程接口
使用TCP/IP协议的应用程序通常采用两种应用编程接口(API):socket和TLI(运输层接口:Transport Layer Interface)。前者有时称作“Berkeley socket”,表明它是从伯克利版发展而来的。后者起初是由AT&T开发的,有时称作XTI(X/Open传输接口),以承认X/Open这个自己定义标准的国际计算机生产产商所做的工作。XTI实际上是TLI的一个超集。
本书不是一本编程方面的书,但是偶尔会引用一些内容来说明TCP/IP的特性,不管大多数的API(socket)是否提供它们。所有关于socket和TLI的编程细节请参阅文献[Stevens 1990]。
1.16 测试网络
图1.11是本书中所有的例子运行的测试网络。为阅读时参考方便,该图还复制在本书的封面内侧。
图1.11 本书例子运行的测试网络,所有的IP地址均从140.252开始编址。
在这个图中(作者的子网),大多数的例子都运行在下面四个系统中。图中所有的IP地址属于B类地址,网络号为140.252。所有的主机名属于.tuc.noao.edu这个域。(noao代表National Optical Astronomy Observatories,tuc代表Tucson)。例如,右下方的系统有一个完整的名字: svr4.tuc.noao.edu,其IP地址是:140.252.13.34。每个方框上方的名称是该主机运行的操作系统。这一组系统和网络上的主机及路由器运行于不同的TCP/IP实现。
需要指出的是,noao.edu这个域中的网络和主机要比图1.11中的多得多。这里列出来的只是本书中将要用到的系统。
在3.4节中,我们将描述这个网络所用到的子网形式,在4.6中我们将更介绍sun与netb之间的拔号SLIP的有关细节。2.4节将详细讨论SLIP。
1.17 小结
本章快速地浏览了TCP/IP协议族,介绍了我们在后面的章节中将要详细讨论的许多术语和协议。
TCP/IP协议族分为四层:链路层,网络层,运输层和应用层,每一层各有不同的责任。在TCP/IP中,网络层和运输层之间的区别是最为关键的:网络层(IP)提供点到点的服务,而运输层(TCP和UDP)提供端到端的服务。
一个互连网是网络的网络。构造互连网的共同基石是路由器,它们在IP层把网络连在一起。第一个字母大写的Internet是指分布在世界各地的大型互连网,其中包括1万多个网络和超过100万台主机。
在一个互连网上,每个接口都用IP地址来标识,尽管用户习惯使用主机名而不是IP地址。域名系统为主机名和IP地址之间提供动态的映射。端口号用来标识互相通信的应用程序。服务器使用众所周知的端口号,而客户使用临时设定的端口号。
习题
1.1 请计算最多有多少个A类、B类和C类网络号。
1.2 用匿名FTP(见27.3节)从主机nic.merit.edu 上获取文件nsfnet/statistics/history.netcount。该文件包含在NSFNET网络上登记的国内和国外的网络数。画一坐标系,横坐标代表年,纵坐标代表网络总数的对数值。纵坐标的最大值是习题1.1的结果。如果数据显示一个明显的趋势,请估计按照当前的编址体制推算,何时会用完所有的网络地址。(3.10节讨论解决该难题的建议。)
1.3 获取一份主机需求RFC拷贝[Braden 1989a],阅读有关应用于TCP/IP协议族每一层的稳健性原则。这个原则的参考对象是什么?
1.4 获取一份最新的赋值RFC拷贝。“quote of the day"协议的有名端口号是什么?哪个RFC对该协议进行了定义?
1.5 如果你有一个接入TCP/IP互连网的主机帐号,它的主IP地址是多少?这台主机是否接入了Internet?它是多接口主机吗?
1.6 获取一份RFC 1000的拷贝,了解RFC这个术语从何而来。
1.7 与Internet协会联系,isoc@isoc.org或者+1 703 648 9888,了解有关加入的情况。
1.8 用匿名FTP从主机is.internic.net处获取文件about-internic/information-about-the-internic。
1-1
2 链路层
2.1 引言
从图1.4我们可以看出,在TCP/IP协议族中,链路层主要有三个目的:(1)为IP模块发送和接收IP数据报;(2)为ARP模块发送ARP请求和接收ARP应答;(3)为RARP发送RARP请求和接收RARP应答。TCP/IP支持多种不同的链路层协议,这取决于网络所使用的硬件,如以太网,令牌环网,FDDI(光纤分布式数据接口),RS-232串行线路等。
在本章中,我们将详细讨论以太网链路层协议,两个串行接口链路层协议(SLIP和PPP),以及大多数实现都包含的环回(loopback)驱动程序。以太网和SLIP是本书中大多数例子使用的链路层。我们对MTU(最大传输单元)进行了介绍,这个概念在本书的后面章节中将多次遇到。我们还讨论了如何为串行线路选择MTU。
2.2 以太网和IEEE 802封装
以太网这个术语一般是指数字设备公司(Digital Equipment Corp.)、 英特尔公司(Intel Corp.)、和Xerox公司联合在1982年公布的一个标准。它是当今TCP/IP采用的主要的局域网技术。它采用一种称作CSMA/CD的媒体接入方法,其意思是载波侦听多路接入/冲突检测(Carrier Sense, Multiple Access with Collision Detection)。它的速率为10 Mb/s,地址为48 bit。
几年后,IEEE(电子电气工程师协会)802委员会公布了一个稍有不同的标准集,其中802.3针对了整个CSMA/CD网络,802.4针对令牌总线网络,802.5针对令牌环网络。这三者的共同特性由802.2标准来定义,那就是802网络共有的逻辑链路控制(LLC)。不幸的是,802.2和802.3定义了一个与以太网不同的帧格式。文献[Stallings 1987]对所有的IEEE 802标准进行了详细的介绍。
在TCP/IP世界中,以太网IP数据报的封装是在RFC 894[Hornig 1984]中定义的,IEEE 802网络的IP数据报封装是在RFC 1042[Postel and Reynolds 1988]中定义的。主机需求RFC要求每台Internet主机都与一个10Mbit/s的以太网电缆相连接:
1. 必须能发送和接收采用RFC 894(以太网)封装格式的分组。
2. 应该能接收与RFC 894混合的RFC 1042(IEEE 802)封装格式的分组。
3. 也许能够发送采用RFC 1042格式封装的分组。如果主机能同时发送两种类型的分组数据,那么发送的分组必须是可以设置的,而且默认条件下必须是RFC 894分组。
最常使用的封装格式是RFC 894定义的格式。图2.1显示了两种不同形式的封装格式。图中每个方框下面的数字是它们的字节长度。
两种帧格式都采用48 bit(6字节)的目标地址和源地址。(802.3允许使用16 bit的地址,但一般是48 bit地址。)这就是我们在本书中所称的硬件地址。ARP和RARP协议(第4章和第5章)对32 bit的IP地址和48 bit的硬件地址进行映射。
接下来的2个字节在两种帧格式中互不相同。在802标准定义的帧格式中,长度字段是指它后续数据的字节长度,但不包括CRC检验码。以太网的类型字段定义了后续数据的类型。在802标准定义的帧格式中,类型字段则由后续的子网接入协议(Sub-network Access Protocol,SNAP)的首部给出。幸运的是,802定义的有效长度值与以太网的有效类型值无一相同,这样,就可以对两种帧格式进行区分。
在以太网帧格式中,类型字段之后就是数据,而在802帧格式中,跟随在后面的是3字节的802.2 LLC和5字节的802.2 SNAP。目的服务访问点(Destination Service Access Point, DSAP)和源服务访问点(Source Service Access Point, SSAP)的值都设为0xaa。ctrl字段的值设为3。随后的3个字节org code都置为0。再接下来的2个字节类型字段和以太网帧格式一样。(其他类型字段值可以参见RFC 1340 [Reynolds and Postel 1992])。
CRC字段用于帧内后续字节差错的循环冗余码检验(检验和)。(它也被称为FCS或帧检验序列)
802.3标准定义的帧和以太网的帧都有最小长度要求。802.3规定数据部分必须至少为38字节,而对于以太网,则要求最少要有46字节。为了保证这一点,必须在不足的空间插入填充(pad)字节。我们在开始观察线路上的分组时将遇到这种最小长度的情况。
在本书中,我们在需要的时候将给出以太网的封装格式,因为这是最为常见的封装格式。
图2.1 IEEE 802.2/802.3(RFC 1042)和以太网的封装格式(RFC 894)
2.3 尾部封装
RFC 893[Leffler and Karels 1984]描述了另一种用于以太网的封装格式,称作尾部封装(trailer encapsulation)。这是一个早期BSD系统在DEC VAX机上运行时的试验格式,它通过调整IP数据报中字段的次序来提高性能。在以太网数据帧中,开始的那部分是变长的字段(IP首部和TCP首部)。把它们移到尾部(在CRC之前),这样当把数据复制到内核时,就可以把数据帧中的数据部分映射到一个硬件页面,节省内存到内存的复制过程。TCP数据报的长度是512字节的整数倍,正好可以用内核中的页表来处理。两台主机通过协商使用ARP扩展协议对数据帧进行尾部封装。这些数据帧需定义不同的以太网帧类型值。
现在,尾部封装已遭到反对,因此我们不对它举任何例子。有兴趣的读者请参阅RFC 893以及文献[Leffler et al. 1989]的11.8节。
2.4 SLIP:串行线路IP
SLIP的全称是Serial Line IP。它是一种在串行线路上对IP数据报进行封装的简单形式,在RFC 1055[Romkey 1988]中有详细描述。SLIP适用于家庭中每台计算机几乎都有的RS-232串行端口和高速调制解调器接入Internet。
下面的规则描述了SLIP协议定义的帧格式:
1.IP数据报以一个称作END(0xc0)的特殊字符结束。同时,为了防止数据报到来之前的线路噪声被当成数据报内容,大多数实现在数据报的开始处也传一个END字符。(如果有线路噪声,那么END字符将结束这份错误的报文。这样当前的报文得以正确的传输,而前一个错误报文交给上层后,会被发现其内容毫无意义而被丢弃。)
2.如果IP报文中某个字符为END,那么就要连续传输两个字节0xdb, 0xdc来取代它。0xdb这个特殊字符被称作SLIP的ESC字符,但是它的值与ASCII码的ESC字符(0x1b)不同。
3. 如果IP报文中某个字符为SLIP的ESC字符,那么就要连续传输两个字节0xdb,0xdd来取代它。
图2.2中的例子就是含有一个END字符和一个ESC字符的IP报文。在这个例子中,在串行线路上传输的总字节数是原IP报文长度再加4个字节。
SLIP是一种简单的帧封装方法,还有一些值得一提的缺陷:
1. 每一端必须知道对方的IP地址。没有办法把本端的IP地址通知给另一端。
2. 数据帧中没有类型字段(类似于以太网中的类型字段)。如果一条串行线路用于SLIP,那么它不能同时使用其他协议。
3. SLIP没有在数据帧中加上检验和(类似于以太网中的CRC字段)。如果SLIP传输的报文被线路噪声影响而发生错误,只能通过上层协议来发现。(另一种方法是,新型的调制解调器可以检测并纠正错误报文。)这样,上层协议提供某种形式的CRC就显得很重要。在第3章和第17章中,我们将看到IP首部和TCP首部及其数据始终都有检验和。在第11章中,我们将看到UDP首部及其数据的检验和却是可选的。
图2.2 SLIP报文的封装
尽管存在这些缺点,SLIP仍然是一种广泛使用的协议。
(下面是原书p.25①的译文)
SLIP的历史要追溯到1984年,Rick Adams第一次在4.2BSD系统中实现。尽管它本身的描述是一种非标准的协议,但是随着调制解调器的速率和可靠性的提高,SLIP越来越流行。现在,它的许多产品可以公开获得,而且很多产家都支持这种协议。
2.5 压缩的SLIP
由于串行线路的速率通常较低(19200 b/s或更低),而且通信经常是交互式的(如Telnet和Rlogin,二者都使用TCP),因此在SLIP线路上有许多小的TCP分组进行交换。为了传送1个字节的数据需要20个字节的IP首部和20个字节的TCP首部,总数超过40个字节。(19.2节描述了Rlogin会话过程中,当敲入一个简单命令时这些小报文传输的详细情况。)
既然承认这些性能上的缺陷,于是人们提出一个被称作CSLIP(即压缩SLIP)的新协议,它在RFC 1144[Jacobson 1990a]中被详细描述。CSLIP一般能把上面的40个字节压缩到3或5个字节。它能在CSLIP的每一端维持多达16个TCP连接,并且知道其中每个连接的首部中的某些字段一般不会发生变化。对于那些发生变化的字段,大多数只是一些小的数字和的改变。这些被压缩的首部大大地缩短了交互响应时间。
(下面是原书p.25②的译文)
现在大多数的SLIP产品都支持CSLIP。作者所在的子网(参见封面内页)中有两条SLIP链路,它们均是CSLIP链路。
2.6 PPP:点对点协议
PPP,点对点协议修改了SLIP协议中的所有缺陷。PPP包括以下三个部分:
1.在串行链路上封装IP数据报的方法。PPP既支持数据为8位和无奇偶检验的异步模式(如大多数计算机上都普遍存在的串行接口),还支持面向比特的同步链接。
2.建立、配置及测试数据链路的链路控制协议(LCP:Link Control Protocol)。它允许通信双方进行协商,以确定不同的选项。
3.针对不同网络层协议的网络控制协议(NCP:Network Control Protocol)体系。当前RFC定义的网络层有IP,OSI网络层,DECnet,以及AppleTalk。例如,IP NCP允许双方商定是否对报文首部进行压缩,类似于CSLIP。(缩写词NCP也可用在TCP的前面)。
RFC 1548[Simpson 1993]描述了报文封装的方法和链路控制协议。RFC 1332[McGregor 1992]描述了针对IP的网络控制协议。
PPP数据帧的格式看上去很像ISO的HDLC(高层数据链路控制)标准。图2.3是PPP数据帧的格式。
PPP数据帧的格式
每一帧都以标志字符0x7e开始和结束。紧接着是一个地址字节,值始终是0xff,然后是一个值为0x03的控制字节。
接下来是协议字段,类似于以太网中类型字段的功能。当它的值为0x0021时表示信息字段是一个IP数据报,值为0xc021时表示信息字段是链路控制数据,值为0x8021时表示信息字段是网络控制数据。
CRC字段(或FCS,帧校验序列)是一个循环冗余检验码,以检测数据帧中的错误。
由于标志字符的值是0x7e,因此当该字符出现在信息字段中时,PPP需要对它进行转义。在同步链路中,该过程是通过一种称作比特填充(bit stuffing)的硬件技术来完成的[Tanenbaum 1989]。在异步链路中,特殊字符0x7d用作转义字符。当它出现在PPP数据帧中时,那么紧接着的字符的第六个比特要取其补码,具体实现过程如下:
1. 当遇到字符0x7e时,需连续传送两个字符:0x7d和0x5e,以实现标志字符的转义。
2. 当遇到转义字符0x7d时,需连续传送两个字符:0x7d和0x5d,以实现转义字符的转义。
3. 默认情况下,如果字符的值小于0x20(比如,一个ASCII控制字符),一般都要进行转义。例如,遇到字符0x01时需连续传送0x7d和0x21两个字符。(这时,第六个比特取补码后变为1,而前面两种情况均把它变为0。)
这样做的原因是防止它们出现在双方主机的串行接口驱动程序或调制解调器中,因为有时它们会把这些控制字符解释成特殊的含义。另一种可能是用链路控制协议来指定是否需要对这32个字符中的某一些值进行转义。默认情况下是对所有的32个字符都进行转义。
与SLIP类似,由于PPP经常用于低速的串行链路,因此减少每一帧的字节数可以降低应用程序的交互时延。利用链路控制协议,大多数的产品通过协商可以省略标志符和地址字段,并且把协议字段由2个字节减少到1个字节。如果我们把PPP的帧格式与前面的SLIP的帧格式(图2.2)进行比较会发现,PPP只增加了3个额外的字节:1个字节留给协议字段,另2个给CRC字段使用。另外,使用IP网络控制协议,大多数的产品可以通过协商采用Van Jacobson报文首部压缩方法(对应于CSLIP压缩),减小IP和TCP首部长度。
总的来说,PPP比SLIP具有下面这些优点:(1)PPP支持在单根串行线路上运行多种协议,不只是IP协议;(2)每一帧都有循环冗余检验;(3)通信双方可以进行IP地址的动态协商(使用IP网络控制协议);(4)与CSLIP类似,对TCP和IP报文首部进行压缩;(5)链路控制协议可以对多个数据链路选项进行设置。为这些优点我们付出的代价是在每一帧的首部增加3个字节,当建立链路时要发送几帧协商数据,以及更为复杂的实现。
(下面是原书p.27①的译文)
尽管PPP比SLIP有更多的优点,但是现在的SLIP用户仍然比PPP用户多。随着产品越来越多,产家也开始逐渐支持PPP,因此最终PPP应该取代SLIP。
2.7 环回接口
大多数的产品都支持环回接口(Loopback Interface),以允许运行在同一台主机上的客户程序和服务器程序通过TCP/IP进行通信。A类网络号127就是为环回接口预留的。根据惯例,大多数系统把IP地址127.0.0.1分配给这个接口,并命名为localhost。一个传给环回接口的IP数据报不能在任何网络上出现。
我们想象,一旦传输层检测到目的端地址是环回地址时,应该可以省略部分传输层和所有网络层的逻辑操作。但是大多数的产品还是照样完成传输层和网络层的所有过程,只是当IP数据报离开网络层时把它返回给自己。
图2.4是环回接口处理IP数据报的简单过程。
图2.4 环回接口处理IP数据报的过程
需要指出图中的关键点是:
1. 传给环回地址(一般是127.0.0.1 )的任何数据均作为IP输入。
2. 传给广播地址或多播地址的数据报复制一份传给环回接口,然后送到以太网上。这是因为广播传送和多播传送的定义(第12章)包含主机本身。
3. 任何传给该主机IP地址的数据均送到环回接口。
看上去用传输层和IP层的方法来处理环回数据似乎效率不高,但它简化了设计,因为环回接口可以被看作是网络层下面的另一个链路层。网络层把一份数据报传送给环回接口,就像传给其他链路层一样,只不过环回接口把它返回到IP的输入队列中。
在图2.4中,另一个隐含的意思是送给主机本身IP地址的IP数据报一般不出现在相应的网络上。例如,在一个以太网上,分组一般不被传出去然后读回来。某些BSD以太网的设备驱动程序的注释说明,许多以太网接口卡不能读回它们自己发送出去的数据。由于一台主机必须处理发送给自己的IP数据报,因此图2.4所示的过程是最为简单的处理办法。
(下面是原书p.29①的译文)
4.4BSD系统定义了变量useloopback,并初始化为1。但是,如果这个变量置为0,以太网驱动程序就会把本地分组送到网络,而不是送到环回接口上。它也许不能工作,这取决于你所使用的以太网接口卡和设备驱动程序。
2.8 最大传输单元MTU
正如我们在图2.1看到的那样,以太网和802.3对数据帧的长度都有一个限制,其最大值分别是1500和1492字节。链路层的这个特性称作MTU,最大传输单元。不同类型的网络大多数都有一个上限。
如果IP层有一个数据报要传,而且数据的长度比链路层的MTU还大,那么IP层就需要进行分片(fragmentation),把数据报分布若干片,这样每一片都小于MTU。我们将在11.5节讨论IP分片的过程。
图2.5列出了一些典型的MTU值,它们摘自RFC 1191[Mogul and Deering 1990]。点到点的链路层(如SLIP和PPP)的MTU并非指的是网络媒体的物理特性。相反,它是一个逻辑限制,目的是为交互使用提供足够快的响应时间。在2.10节中,我们将看到这个限制值是如何计算出来的。
在3.9节中,我们将用netstat命令打印出网络接口的MTU。
图2.5 几种常见的最大传输单元(MTU)
2.9 路径MTU
当在同一个网络上的两台主机互相进行通信时,该网络的MTU是非常重要的。但是如果两台主机之间的通信要通过多个网络,那么每个网络的链路层就可能有不同的MTU。重要的不是两台主机所在网络的MTU的值,重要的是两台通信主机路径中的最小MTU。它被称作路径MTU。
两台主机之间的路径MTU不一定是个常数。它取决于当时所选择的路由。而路由选择不一定是对称的(从A到B的路由可能与从B到A的路由不同),因此路径MTU在两个方向上不一定是一致的。
RFC 1191[Mogul and Deering 1990]描述了路径MTU的发现机制,即在任何时候确定路径MTU的方法。我们在介绍了ICMP和IP分片方法以后再来看它是如何操作的。在11.6节中,我们将看到ICMP的不可到达错误就采用这种发现方法。在11.7节中,我们还会看到,traceroute程序也是用这个方法来确定到达目标节点的路径MTU。在 11.8节和24.2节,我们将介绍当产品支持路径MTU的发现方法时,UDP和TCP是如何进行操作的。
2.10 串行线路吞吐量计算
如果线路速率是9600 b/s,而一个字节有8 bit,加上一个起始比特和一个停止比特,那么线路的速率就是960 B/s(字节/秒)。以这个速率传输一个1024字节的分组需要1066 ms。如果我们用SLIP链接运行一个交互式应用程序,同时还运行另一个应用程序如FTP发送或接收1024字节的数据,那么一般来说我们就必须等待一半的时间(533 ms)才能把交互式应用程序的分组数据发送出去。
假定我们的交互分组数据可以在其它“大块”分组数据发送之前被发送出去。大多数的SLIP实现确实提供这类服务排队方法,把交互数据放在大块的数据前面。交互通信一般有Telnet,Rlogin,以及FTP的控制部分(用户的命令,而不是数据)。
(下面是原书p.31①的译文)
这种服务排队方法是不完善的。它不能影响已经进入下游(如串行驱动程序)队列的非交互数据。同时,新型的调制解调器具有很大的缓冲区,因此非交互数据可能已经进入该缓冲区了。
对于交互应用来说,等待533 ms是不能接受的。关于人的有关研究表明,交互响应时间超过100-200 ms就被认为是不好的[Jacobson 1990a]。这是发送一份交互报文出去后,直到接收到响应信息(通常是出现一个回显字符)为止的往返时间。
把SLIP的MTU缩短到256就意味着链路传输一帧最长需要266 ms,它的一半是133 ms(这是我们一般需要等待的时间)。这样情况会好一些,但仍然不完美。我们选择它的原因(与64或128相比)是因为大块数据提供良好的线路利用率(如大文件传输)。假设CSLIP的报文首部是5个字节,数据帧总长为261个字节,256个字节的数据使线路的利用率为98.1%,帧头占了1.9%,这样的利用率是很不错。如果把MTU降到256以下,那么将降低传输大块数据的最大吞吐量。
在图2.5列出的MTU值中,点对点链路的MTU是296个字节。假设数据为256字节,TCP和IP首部占40个字节。由于MTU是IP向链路层查询的结果,因此该值必须包括通常的TCP和IP首部。这样就会导致IP如何进行分片的决策。IP对于CSLIP的压缩情况一无所知。
我们对平均等待时间的计算(传输最大数据帧所需时间的一半)只适用于SLIP链路(或PPP链路)在交互通信和大块数据传输这两种情况下。当只有交互通信时,如果线路速率是9600 b/s,那么任何方向上的1字节数据(假设有5个字节的压缩帧头)往返一次都大约需要12.5 ms。它比前面提到的100-200 ms足够小。需要注意的是,由于帧头从40个字节压缩到5个字节,使得1字节数据往返时间从85 ms减到12.5 ms。
不幸的是,当使用新型的纠错和压缩调制解调器时,这样的计算就更难了。这些调制解调器所采用的压缩方法使得在线路上传输的字节数大大减少,但纠错机制又会增加传输的时间。不过,这些计算是我们进行合理决策的入口点。
在后面的章节中,我们将用这些串行线路吞吐量的计算来验证数据从串行线路止通过的时间。
2.11 小结
本章讨论了Internet协议族中的最底层协议,链路层协议。我们比较了以太网和IEEE 802.2/802.3的封装格式,以及SLIP和PPP的封装格式。由于SLIP和PPP经常用于低速的链路,二者都提供了压缩不常变化的公共字段的方法。这使交互性能得到提高。
大多数的实现都提供环回接口。访问这个接口可以通过特殊的环回地址,一般为127.0.0.1,也可以通过发送IP数据报给主机所拥有的任一IP地址。当环回数据回到上层的协议栈中时,它已经过传输层和IP层完整的处理过程。
我们描述了很多链路都具有一个重要特性,MTU,相关的一个概念是路径MTU。根据典型的串行线路MTU,我们对SLIP和CSLIP链路的传输时延进行了计算。
本章内容只覆盖了当今TCP/IP所采用部分数据链路公共技术。TCP/IP成功的原因之一是它几乎能在任何数据链路技术上运行。
习题
2.1 如果你的系统支持netstat(1)命令(参见3.9小节),那么请用它确定系统上的接口及其MTU。
2-1
3 IP:网际协议
3.1 引言
IP是TCP/IP协议族中最为核心的协议。所有的TCP,UDP,ICMP,及IGMP数据都以IP数据报格式传输(图1.4)。许多刚开始接触TCP/IP的人对IP提供不可靠、无连接的数据报传送服务感到很奇怪,特别是那些具有X.25或SNA背景知识的人。
不可靠(unreliable)的意思是它不能保证IP数据报能成功地到达目的地。IP仅提供最好的传输服务。如果发生某种错误时,如某个路由器暂时用完了缓冲区,IP有一个简单的错误处理算法:丢弃该数据报,然后发送ICMP消息报给信源端。任何要求的可靠性必须由上层来提供(如TCP)。
无连接(connectionless)这个术语的意思是IP并不维护任何关于后续数据报的状态信息。每个数据报的处理是相互独立的。这也说明,IP数据报可以不按发送顺序接收。如果一信源向相同的信宿发送两个连续的数据报(先是A,然后是B),每个数据报都是独立地进行路由选择,可能选择不同的路线,因此B可能在A到达之前先到达。
在本章,我们将简要介绍IP首部中的各个字段,讨论IP路由选择和子网的有关内容。我们还要介绍两个有用的命令:ifconfig和netstat。关于IP首部中一些字段的细节,我们将留在以后使用这些字段的时候再进行讨论。RFC 791[Postel 1981a]是IP的正式规约文件。
3.2 IP首部
IP数据报的格式如图3.1所示。普通的IP首部长为20个字节,除非含有选项字段。
图3.1 IP数据报格式及首部中的各字段
我们来分析图3.1中的首部。最高位在左边,记为0 bit,最低位在右边,记为31 bit。
4个字节的32 bit值以下面的次序传输:首先是0-7 bit,其次8-15 bit,然后16-23 bit,最后是24-31 bit。这种传输次序称作big endian字节次序。由于TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节次序。以其他形式存储二进制整数的机器,如little endian格式,则必须在传输数据之前把首部转换成网络字节次序。
目前的协议版本号是4,因此IP有时也称作IPv4。3.10节将对一种新版的IP协议进行讨论。
首部长度指的是首部占32 bit字的数目,包括任何先期选项。由于它是一个4比特字段,因此首部最长为60个字节。在第8章中,我们将看到这种限制使某些选项如路由记录选项在当今已没有什么用处。普通IP数据报(没有任何选择项)该字段的值是5。
服务类型(TOS)字段包括一个3 bit的优先权子字段(现在已被忽略),4 bit的TOS子字段,和1 bit未用位但必须置0。4 bit的TOS分别代表:最小时延,最大吞吐量,最高可靠性,最小费用。4 bit中只能置其中1 bit。如果所有4 bit均为0,那么就意味着是普遍服务。RFC 1340 [Reynolds and Postel 1992]描述了所有的标准应用如何设置这些服务类型。RFC 1349 [Almquist 1992]对该RFC进行了修正,更为详细地描述了TOS的特性。
图3.2列出了对不同应用建议的TOS值。在最后一列中,我们给出的是十六进制值,因为这就是在后面我们将要看到的tcpdump命令输出。
图3.2 服务类型字段推荐值
Telnet和Rlogin这两个交互应用要求最小的传输时延,因为人们主要用它们来传输少量的交互数据。另一方面,FTP文件传输则要求有最大的吞吐量。最高可靠性被指明给网络管理(SNMP)和路由选择协议。用户网络新闻(Usenet news, NNTP)是唯一要求最小费用的应用。
现在大多数的TCP/IP实现都不支持TOS特性,但是自4.3BSD Reno以后的新版系统都对它进行了设置。另外,新的路由协议如OSPF和IS-IS都能根据这些字段的值进行路由决策。
(下面是原书p.35①的译文)
在2.10节中,我们提到SLIP一般提供基于服务类型的排队方法,允许对交互通信数据在处理大块数据之前进行处理。由于大多数的实现都不使用TOS字段,因此这种排队机制由SLIP自己来判断和处理,驱动程序先查看协议字段(确定是否是一个TCP段),然后检查TCP信源和信宿的端口号,以判断是否是一个交互服务。一个驱动程序的注释这样认为,这种“令人厌恶的处理方法”是必需的,因为大多数实现都不允许应用程序设置TOS字段。
总长度字段是指整个IP数据报的长度,以字节为单位。利用首部长度字段和总长度字段,我们就可以知道IP数据报中数据内容的起始位置和长度。由于该字段长16比特,所以IP数据报最长可达65535字节。(回忆图2.5,超级通道的MTU为65535。它的意思其实不是一个真正的MTU-—它使用了最长的IP数据报。)当数据报被分片时,该字段的值也随着变化,这一点我们将在11.5节中进一步描述。
尽管可以传送一个长达65535字节的IP数据报,但是大多数的链路层都会对它进行分片。而且,主机也要求不能接收超过576字节的数据报。由于TCP把用户数据分成若干片,因此一般来说这个限制不会影响TCP。我们在后面的章节中将遇到大量使用UDP的应用(RIP,TFTP,BOOTP,DNS,以及SNMP),它们都限制用户数据报长度为512字节,小于576字节。但是,事实上现在大多数的实现(特别是那些支持网络文件系统,NFS的实现)允许超过8192字节的IP数据报。
总长度字段是IP首部中必要的内容,因为一些数据链路(如以太网)需要填充一些数据以达到最小长度。尽管以太网的最小帧长为46字节(图2.1),但是IP数据可能会更短。如果没有总长度字段,那么IP层就不知道46字节中有多少是IP数据报的内容。
标识字段唯一地标识主机发送的每一份数据报。通常每发送一份报文它的值就会加1。我们在11.5节介绍分片和重组时再详细讨论它。同样,在讨论分片时我们再来分析标志字段和片偏移字段。
(下面是原书p.36①的译文)
RFC 791 [Postel 1981a]认为标识字段应该由让IP发送数据报的上层来选择。假设有两个连续的IP数据报,其中一个是由TCP生成的,而另一个是由UDP生成的,那么它们可能具有相同的标识字段。尽管这也可以照常工作(由重组算法来处理),但是在大多数从伯克利派生出来的系统中,每发送一个IP数据报时,IP层都要把一个内核变量的值加1,不管交给IP的数据来自哪一层。内核变量的初始值根据系统引导时的时间来设置。
生存时间字段(time-to-live)TTL设置了数据报可以经过的最多路由器数。它指定了数据报的生存时间。TTL的初始值由源主机设置(通常为32或64),一旦经过一个处理它的路由器,它的值就减去1。当该字段的值为0时,数据报就被丢弃,并发送ICMP报文通知源主机。第8章我们讨论Traceroute程序时将再回来讨论该字段。
我们已经在第1章讨论了协议字段,并在图1.8中示出了它如何被IP用来对数据报进行分用。根据它可以识别是哪个协议向IP传送数据。
首部检验和字段是根据IP首部计算的检验和码。它不对首部后面的数据进行计算。ICMP,IGMP,UDP和TCP在它们各自的首部中均含有同时覆盖首部和数据检验和码。
为了计算一份数据报的IP检验和,首先把检验和字段置为0。然后,对首部中每个16 bit的二进制反码进行求和(整个首部看成是由一串16 bit的字组成),结果存在检验和字段中。当收到一份IP数据报后,同样对首部中每个16 bit的二进制反码进行求和。由于收方在计算过程中包含了发方存在首部中的检验和,因此首部在传输过程中没有发生任何差错时,收方计算的结果应该为全1。如果结果不是全1(即检验和错误),那么IP就丢弃收到的数据报。但是不生成差错报文,由上层去发现丢失的数据报并进行重传。
ICMP,IGMP,UDP和TCP都采用相同的检验和算法,尽管TCP和UDP除了本身的首部和数据外,在IP首部中还包含不同的字段。在RFC 1071[Braden,Borman and Patridge 1988]中有关于如何计算Internet检验和的实现技术。由于路由器经常只修改TTL字段(减1),因此当路由器转发一份报文时可以增加它的检验和,而不需要对IP整个首部进行重新计算。RFC 1141[Mallory and Kullberg 1990]为此给出了一个很有效的方法。
(下面是原书p.37①的译文)
但是,标准的BSD实现在转发数据报时并不是采用这种增加的办法。
每一份IP数据报都包含源IP地址和目的IP地址。我们在1.4节中说过,它们都是32 bit的值。
最后一个字段是任选项,是数据报中的一个可变长的可选信息。目前,这些任选项定义如下:
•安全和处理限制(用于军事领域,详细内容参见RFC 1108[Kent 1991])
•记录路径(让每个路由器都记下它的IP地址,见7.3节)
•时间戳(让每个路由器都记下它的IP地址和时间,见7.4节)
•宽松的源站选路(为数据报指定一系列必须经过的IP地址,见8.5节)
•严格的源站选路(与宽松的源站选路类似,但是它要求只能经过指定的这些地址,不能经过其它的地址)。
这些选项很少被使用,并非所有的主机和路由器都支持这些选项。
选项字段一直都是以32 bit作为界限,在必要的时候插入值为0的填充字节。这样就保证IP首部始终是32 bit的整数倍(这是首部长度字段所要求的)。
3.3 IP路由选择
从概念上说,IP路由选择是简单的,特别对于主机来说。如果目的主机与源主机直接相连(如点对点链路)或都在一个共享网络上(以太网或令牌环网),那么IP数据报就直接送到目的主机上。否则,主机把数据报发往一默认的路由器上,由路由器来转发该数据报。大多数的主机都是采用这种简单机制。
在本节和第9章中,我们将讨论更一般的情况,即IP层既可以配置成路由器的功能,也可以配置成主机的功能。当今的大多数多用户系统,包括几乎所有的Unix系统,都可以配置成一个路由器。我们可以为它指定主机和路由器都可以使用的简单路由算法。根本上的区别在于主机从不把数据报从一个接口转发到另一个接口,而路由器则要转发数据报。内含路由器功能的主机应该从不转发数据报,除非它被设置成那样。在9.4小节中,我们将进一步讨论配置的有关问题。
在一般的体制中,IP可以从TCP,UDP,ICMP,IGMP接收数据报(即在本地生成的数据报)并进行发送,或者从一个网络接口接收数据报(待转发的数据报)进行发送。IP层在内层中有一个路由表。当收到一份数据报进行发送时,它都要对该表搜索一次。当数据报来自某个网络接口时,IP首先检查目的IP地址是否为本机的IP地址之一或者IP广播地址。如果确实是这样,数据报就被送到由IP首部协议字段所指定的协议模块进行处理。如果数据报的目的不是这些地址,那么(1)如果IP层被设置为路由器的功能,那么就对数据报进行转发(也就是说,像下面对待发出的数据报一样处理),否则(2)数据报被丢弃。
路由表中的每一项都包含下面这些信息:
•目的IP地址。它既可以是一个完整的主机地址,也可以是一个网络地址,由该表目中的标志字段来指定(如下所述)。主机地址有一个非0的主机号(图1.5),以指定某一特定的主机,而网络地址中的主机号为0,以指定网络中的所有主机(如以太网,令牌环网)。
•下一站(或下一跳)路由器(next-hop router)的IP地址,或者有直接连接的网络IP地址。下一站路由器是指一个在直接相连网络上的路由器,通过它可以转发数据报。下一站路由器不是最终的目的,但是它可以把我们传送给它的数据报转发到最终目的。
•标志。其中一个标志指明目的IP地址是网络地址还是主机地址,另一个标志指明下一站路由器是否为真正的下一站路由器,还是一个直接相连的接口。(我们将在9.2节中详细介绍这些标志。)
•为数据报的传输指定一个网络接口。
IP路由选择是逐跳地(hop-by-hop)进行的。从这个路由表信息可以看出,IP并不知道到达任何目的的完整路径(当然,除了那些与主机直接相连的目的)。所有的IP路由选择只为数据报传输提供下一站路由器的IP地址。它假定下一站路由器比发送数据报的主机更接近目的,而且下一站路由器与该主机是直接相连的。
IP路由选择主要完成以下这些功能:
1. 搜索路由表,寻找能与目的IP地址完全匹配的表目(网络号和主机号都要匹配)。如果找到,则把报文发送给该表目指定的下一站路由器或直接连接的网络接口(取决于标志字段的值)。
2. 搜索路由表,寻找能与目的网络号相匹配的表目。如果找到,则把报文发送给该表目指定的下一站路由器或直接连接的网络接口(取决于标志字段的值)。目的网络上的所有主机都可以能过这个表目来处置。例如,一个以太网上的所有主机都是通过这种表目进行寻径的。
这种搜索网络的匹配方法必须考虑可能的子网掩码。关于这一点我们在下一节中进行讨论。
3.搜索路由表,寻找标为“默认”(default)的表目。如果找到,则把报文发送给该表目指定的下一站路由器。
如果上面这些步骤都没有成功,那么该数据报就不能被传送。如果不能传送的数据报来自本机,那么一般会向生成数据报的应用程序返回一个“主机不可达”或“网络不可达”的错误。
完整主机地址匹配在网络号匹配之前执行。只有当它们都失败后才选择默认路由。默认路由,以及下一站路由器发送的ICMP间接报文(如果我们为数据报选择了错误的默认路由),是IP路由选择机制中功能强大的特性。我们在第9章对它们进行讨论。
为一个网络指定一个路由器,而不必为每个主机指定一个路由器,这是IP路由选择机制的另一个基本特性。这样做可以极大地缩小路由表的规模,比如Internet上的路由器有只有几千个表目,而不会是超过100万个表目。
例子
首先考虑一个简单的例子:我们的主机bsdi有一个IP数据报要发送给主机sun。双方都在同一个以太网上(参见封面内侧的图)。数据报的传输过程如图3.3所示。
当IP从某个上层收到这份数据报后,它搜索路由表,发现目的IP地址(140.252.13.133)在一个直接相连的网络上(以太网140.252.13.0)。于是,在表中找到匹配网络地址。(在下一节中,我们将看到,由于以太网的子网掩码的存在,实际的网络地址是140.252.13.32,但是这并不影响这里所讨论的路由选择。)
数据报被送到以太网驱动程序,然后作为一个以太网数据帧被送到sun主机上(图2.1)。IP数据报中的目的地址是sun的IP地址(140.252.13.33),而在链路层首部中的目的地址是48 bit的sun主机的以太网接口地址。这个48 bit的以太网地址是用ARP协议获得的,我们将在下一章对此进行描述。
数据报从主机bsdi到sun的传送过程
现在让我们来看另一个例子:主机bsdi有一份IP数据报要传到ftp.uu.net主机上,它的IP地址是192.48.96.9。经过的前三个路由器如图3.4所示。首先,主机bsdi搜索路由表,但是没有找到与主机地址或网络地址相匹配的表目,因此只能用默认的表目,把数据报传给下一站路由器,即主机sun。当数据报从bsdi被传到sun主机上以后,目的IP地址是最终的信宿机地址(192.48.96.9),但是链路层地址却是sun主机的以太网接口地址。这与图3.3不同,在那里数据报中的目的IP地址和目的链路层地址都指的是相同的主机(sun)。
当sun收到数据报后,它发现数据报的目的IP地址并不是本机的任一地址,而sun已被设置成具有路由器的功能,因此它把数据报进行转发。经过搜索路由表,选用了默认表目。根据sun 的默认表目,它把数据报转发到下一站路由器netb,该路由器的地址是140.252.1.183。数据报是经过点对点SLIP链路被传送的,采用了图2.2所示的最小封装格式。这里,我们没有给出像以太网链路层数据帧那样的首部,因为在SLIP链路中没有那样的首部。
当netb收到数据报后,它执行与sun主机相同的步骤:数据报的目的地址不是本机地址,而netb也被设置成具有路由器的功能,于是它也对该数据报进行转发。采用的也是默认路由表目,把数据报送到下一站路由器gateway(140.252.1.4)。位于以太网140.252.1上的主机netb用ARP获得对应于140.252.1.4的48 bit以太网地址。这个以太网地址就是链路层数据帧头上的目的地址。
路由器gateway也执行与前面两个路由器相同的步骤。它的默认路由表目所指定的下一站路由器IP地址是140.252.104.2。(我们将在图8.4中证实,使用Traceroute程序时,它就是gateway使用的下一站路由器。)
对于这个例子我们需要指出一些关键点:
1. 该例子中的所有主机和路由器都使用了默认路由。事实上,大多数主机和一些路由器可以用默认路由来处理任何目的,除非它在本地局域网上。
图3.4 从bsdi到ftp.uu.net (192.48.96.9)的初始路径
2. 数据报中的目的IP地址始终不发生任何变化。(在8.5节中,我们将看到,只有使用源路由选项时目的IP地址才有可能被修改,但这种情况很少出现。)所有的路由选择决策都是基于这个目的IP地址。
3. 每个链路层可能具有不同的数据帧首部,而且链路层的目的地址(如果有的话)始终指的是下一站的链路层地址。在我们的例子中,两个以太网封装了含有下一站以太网地址的链路层首部,但是SLIP链路没有这样做。以太网地址一般通过ARP获得。
在第9章,我们在描述了ICMP之后将再次讨论IP路由选择问题。我们将看到一些路由表的例子,以及如何用它们来进行路由决策的。
3.4 子网寻址
现在所有的主机都要求支持子网编址(RFC 950 [Mogul and Postel 1985])。不是把IP地址看成由单纯的一个网络号和一个主机号组成,而是把主机号再分成一个子网号和一个主机号。
这样做的原因是因为A类和B类地址为主机号分配了太多的空间,可分别容纳主机数224-2和216-2。事实上,在一个网络中人们并不安排这么多的主机。(各类IP地址的格式如图1.5所示。)由于全0或全1的主机号都是无效的,因此我们把总数减去2。
在InterNIC获得某类IP网络号后,就由当地的系统管理员来进行分配,由他(或她)来决定是否建立子网,以及分配多少比特给子网号和主机号。例如,这里有一个B类网络地址(140 .252),在剩下的16 bit中,8 bit用于子网号,8 bit用于主机号,格式如图3.5所示。这样就允许有254个子网,每个子网可以有254台主机。
图3.5 B类地址的一种子网编址
许多管理员采用自然的划分方法,即把B类地址中留给主机的16 bit中的前8 bit作为子网地址,后8 bit作为主机号。这样用点分十进制方法表示的IP地址就可以比较容易确定子网号。但是,并不要求A类或B类地址的子网划分都要以字节为划分界限。
大多数的子网例子都是B类地址。其实,子网还可用于C类地址,只是它可用的比特数较少而已。很少出现A类地址的子网例子是因为A类地址本身就很少。(但是,大多数A类地址都是进行子网划分的。)
子网对外部路由器来说隐藏了内部网络组织(一个校园或公司内部)的细节。在我们的网络例子中,所有的IP地址都有一个B类网络号140.252。但是其中有超过30个子网,多于400台主机分布在这些子网中。由一台路由器提供了Internet的接入,如图3.6所示。
在这个图中,我们把大多数的路由器编号为Rn,n是子网号。我们给出了连接这些子网的路由器,同时还包括了封二图中的九个系统。在图中,以太网用粗线表示,点对点链路用虚线表示。我们没有画出不同子网中的所有主机。例如,在子网140.252.3上,就超过50台主机,而在子网140.252.1上则超过100台主机。
与30个C类地址相比,用一个包含30个子网的B类地址的好处是,它可以缩小Internet路由表的规模。B类地址140.252被划分为若干子网的事实对于所有子网以外的Internet路由器都是透明的。为了到达IP地址开始部分为140.252的主机,外部路由器只需要知道通往IP地址140.252.104.1的路径。这就是说,对于网络140.252只需一个路由表目,而如果采用30个C类地址,则需要30个路由表目。因此,子网划分缩减了路由表的规模。(在10.8小节中,我们将介绍一种新技术,即使用C类地址也可以缩减路由表的规模。)
图3.6网络noao.edu(140.252)中的大多数子网安排
子网对于子网内部的路由器是不透明的。如图3.6所示,一份来自Internet的数据报到达gateway,它的目的地址是140.252.57.1。路由器gateway需要知道子网号是57,然后把它送到kpno。同样,kpno必须把数据报送到R55,最后由R55把它送到R57。
3.5 子网掩码
任何主机在引导时进行的部分配置是指定主机IP地址。大多数系统把IP地址存在一个磁盘文件里供引导时读用。在第5章我们将讨论一个无盘系统如何在引导时获得IP地址。
除了IP地址以外,主机还需要知道有多少比特用于子网号及多少比特用于主机号。这也是在引导过程中通过子网掩码来确定的。这个掩码是一个32 bit的值,其中值为1的比特留给网络号和子网号,为0的比特留给主机号。图3.7是一个B类地址的两种不同的子网掩网格式。第一个例子是noao.edu网络采用的子网划分方法,如图3.5所示,子网号和主机号都是8 bit宽。第二个例子是一个B类地址划分成10 bit的子网号和6 bit的主机号。
图3.7 两种不同的B类地址子网掩码例子
尽管IP地址一般以点分十进制方法表示,但是子网掩码却经常用十六进制来表示,特别是当界限不是一个字节时,因为子网掩码是一个比特掩码。
给定IP地址和子网掩码以后,主机就可以确定IP数据报的目的是:(1)本子网上的主机;(2)本网络中其它子网中的主机;(3)其它网络上的主机。如果知道本机的IP地址,那么就知道它是否为A类,B类或C类地址(从IP地址的高位可以得知),也就知道网络号和子网号之间的分界限。而根据子网掩码则知道子网号与主机号之间的分界限。
例子
假设我们的主机地址是140.252.1.1(一个B类地址),而子网掩网为255.255.255.0(其中8 bit为子网号,8 bit为主机号)
. 如果目的IP地址是140.252.4.5,那么我们知道B类网络号是相同的(140.252),但是子网号是不同的(1和4)。用子网掩码在两个IP地址之间的比较如图3.8所示。
. 如果目的IP地址是140.252.1.22,那么B类网络号还是一样的(140.252),而且子网号也是一样的(1),但是主机号是不同的。
. 如果目的IP地址是192.43.235.6(一个C类地址),那么网络号是不同的,因而进一步的比较就不用再进行了。
图3.8 使用子网掩码的两个B类地址之间的比较
给定两个IP地址和子网掩码后,IP路由选择功能一直进行这样的比较。
3.6 特殊情况的IP地址
经过子网划分的描述,我们现在介绍7个特殊的IP地址,如图3.9所示。在这个图中,0表示所有的比特位全为0,-1表示所有的比特位全为1,netid, subnetid, 和hostid分别表示不为全0或全1的对应字段。子网号栏为空表示该地址没有进行子网划分。
(以下是图3.9的译文)
IP地址
可以为
描述
网络号
子网号
主机号
源端?
目的端?
0
0
OK
不可能
网络上的主机(参见下面的限制)
0
hostid
OK
不可能
网络上的特定主机(参见下面的限制)
127
任何值
OK
OK
环回地址(2.7节)
-1
-1
不可能
OK
受限的广播(永远不被转发)
netid
-1
不可能
OK
以网络为目标向netid广播
netid
subnetid
-1
不可能
OK
以子网为目标向netid, subnetid广播
netid
-1
-1
不可能
OK
以所有子网为目标向netid广播
图3.9 特殊情况的IP地址
我们把这个表分成三个部分。表的头两项是特殊的源地址,中间项是特殊的环回地址,最后四项是广播地址。
表中的头两项,网络号为0,只能作为初始化过程中的源地址出现,如主机使用BOOTP协议确定本机IP地址时。
在12.2节中,我们将进一步分析四类广播地址。
3.7 一个子网的例子
这个例子是本文中采用的子网,以及如何使用两个不同的子网掩码。具体安排如图3.10所示。
图3.10 作者所在子网中的主机和网络安排
如果把该图与封二中的图相比,你会发现我们在图3.10中省略了从路由器sun到上面的以太网之间的连接细节,实际上它们之间的连接是拔号SLIP。这个细节不影响我们本节中讨论的子网划分问题。我们在4.6节讨论ARP代理时将再回头讨论到这个细节。
问题是我们在子网13中有两个分离的网络:一个以太网和一个点对点链路(硬件连接的SLIP链路)。(点对点链接始终会带来问题,因为它一般在两端都需要IP地址。)将来或许会有更多的主机和网络,但是为了不让主机跨越不同的网络就得使用不同的子网号。我们的解决方法是把子网号从8 bit扩充到11 bit,把主机号从8 bit减为5 bit。这就叫作变长子网,因为140.252网络中的大多数子网都采用8 bit子网掩码,而我们的子网却采用11 bit的子网掩码。
(下面是原书p.46①的译文)
RFC 1009[Braden and Postel 1987]允许一个含有子网的网络使用多个子网掩码。新的路由器需求RFC[Almquist 1993]则要求支持这一功能。
但是,问题在于并不是所有的路由选择协议在交换目的网络时也交换子网掩码。在第10章中,我们将看到RIP不支持变长子网,RIP 2版和OSPF则支持变长子网。在我们的例子中不存在这种问题,因为在我的子网中不要求使用RIP协议。
作者子网中的IP地址结构如图3.11所示,11位子网号中的前8 bit始终是13。在剩下的3 bit中,我们用二进制001表示以太网,010表示点对点SLIP链路。这个变长子网掩码在140.252网络中不会给其它主机和路由器带来问题――只要目的是子网140.252.13的所有数据报都传给路由器sun(IP地址是140.252.1.29),如图3.11所示,而如果sun知道子网13中的主机有11 bit子网号,那么一切都好办了。
图3.11 变长子网
140.252.13子网中的所有接口的子网掩码是255.255.255.224,或0xffffffe0。这表明最右边的5 bit留给主机号,左边的27 bit留给网络号和子网号。
图3.10中所有接口的IP地址和子网掩码的分配情况如图3.12所示。
图3.12 作者子网的IP地址
第一栏标为是“主机”,但是sun和bsdi也具有路由器的功能,因为它们是多接口的,可以把分组数据从一个接口转发到另一个接口。
这个表中的最后一行是图3.10中的广播地址140.252.13.63:它是根据以太网子网号(140.252.13.32)和图3.11中的低5位置1(16+8+4+2+1=31)得来的。(我们在第12章中将看到,这个地址被称作以子网为目标的广播地址(subnet-directed broadcast address)。)
3.8 ifconfig命令
到目前为止,我们已经讨论了链路层和IP层,现在可以介绍TCP/IP对网络接口进行配置和查询的命令了。ifconfig(8)命令一般在引导时运行,以配置主机上的每个接口。
由于拔号接口可能会经常接通和挂断(如SLIP链路),每次线路接通和挂断时ifconfig都必须(以某种方法)运行。这个过程如何完成取决于使用的SLIP软件。
下面是作者子网接口的有关参数。请把它们与图3.12的值进行比较。
(见原书p.48的①)
环回接口(2.7节)被认为是一个网络接口。它是一个A类地址,没有进行子网划分。
需要注意的是以太网没有采用尾部封装(2.3节),而且可以进行广播,而SLIP链路是一个点对点的链接。
SLIP接口的标志LINK0是一个允许压缩slip的数据(CSLIP,参见2.5节)的配置选项。其它的选项有LINK1(如果从另一端收到一份压缩报文,就允许采用CSLIP)和LINK2(所有外出的ICMP报文都被丢弃)。我们在4.6节中将讨论SLIP链接的目的地址。
(下面是原书p.48②的译文)
安装指南中的注释对最后这个选项进行了解释:“一般它不应设置,但是由于一些不当的ping操作,你可能会导致吞吐量降到0。”
bsdi是另一台路由器。由于-a参数是SunOS操作系统具有的功能,因此我们必须多次执行ifconfig,并指定接口名字参数:
(见原书p.48的③)
这里,我们看到以太网接口(we0)的一个新选项:SIMPLEX。这个4.4BSD标志表明接口不能收到本机传送的数据。在BSD/386中所有的以太网都这样设置。一旦这样设置后,如果接口发送一帧数据到广播地址,那么就会为本机拷贝一份数据送到环回地址。(在6.3小节我们将举例子说明这一点。)
在主机slip中,SLIP接口的设置基本上与上面的bsdi一致,只是两端的IP地址进行了互换:
slip % /好好学习in/ifconfig sl0
sl0: flags=1011
inet 140.252.13.65 --> 140.252.13.66 netmask ffffffe0
最后一个接口是主机svr4上的以太网接口。它与前面的以太网接口类似,只是SVR4版的ifconfig没有打印RUNNING标志:
svr4 % /usr/好好学习in/ifconfig emd0
emd0: flags=23
inet 140.252.13.34 netmask ffffffe0 broadcast 140.252.13.63
ifconfig命令一般支持TCP/IP以外的其它协议族,而且有很多参数。关于这些细节你可以查看系统说明书。
3.9 netstat命令
netstat(1)命令也提供系统上的接口信息。-i参数将打印出接口信息,-n参数则打印出IP地址,而不是主机名字。
(见原书p.49的①)
这个命令打印出每个接口的MTU,输入分组数,输入错误,输出分组数,输出错误,冲突,以及当前的输出队列长度。
我们在第9章将用netstat命令检查路由表,那时再回头讨论该命令。另外,在第13章我们将用它的一个改进版本来查看活动的广播组。
3.10 IP的未来
IP主要存在三个方面的问题。这是Internet在过去几年快速增长所造成的结果。(参见习题1.2。)
1. 超过半数的B类地址已被分配。根据当前的估计,如果B类地址继续以当前的速度分配,它们将大约在1995年耗尽。
2. 32 bit的IP地址从长期的Internet增长角度来看一般是不够用的。
3. 当前的路由结构没有层次结构,属于平面型(flat)结构,每个网络都需要一个路由表目。随着网络数目的增长,一个具有多个网络的网站就必须分配多个C类地址,而不是一个B类地址,因此路由表的规模会不断增长。
无类别的域间路由选择CIDR(Classless Interdomain Routing)提出了一个可以解决第三个问题的建议,对当前版本的IP(IP版本4)进行扩充,以适应下个世纪Internet的发展。对此我们将在10.8节进一步详细介绍。
对新版的IP,即下一代IP,经常称作IPng,主要有四个方面的建议。1993年5月发行的IEEE Network (vol.7, no.3)对前三个建议进行了综述,同时有一篇关于CIDR的论文。RFC 1454 [Dixon 1993]对前三个建议进行了比较。
1. SIP,简单Internet协议。它针对当前的IP提出了一个最小幅度的修改建议,采用64位地址和一个不同的首部格式。(首部的前4比特仍然包含协议的版本号,其值不再是4。)
2. PIP。这个建议也采用了更大的,可变长度的,有层次结构的地址,而且首部格式也不相同。
3. TUBA,代表“TCP and UDP with Bigger Address”,它基于OSI 的CLNP(Connectionless Network Protocol,无连接网络协议),一个与IP类似的OSI协议。它提供大得多的地址空间:可变长度,可达20个字节。由于CLNP是一个现有的协议,而SIP和PIP只是建议,因此关于CLNP的文档已经出现。RFC 1347[Callon 1992]提供了TUBA的有关细节。文献[Perlman 1992]的第7章对IPv4和CLNP进行了比较。许多路由器已经支持CLNP,但是很少有主机也提供支持。
4. TP/IX,由RFC 1475 [Ullmann 1993]对它进行了描述。虽然SIP采用了64 bit的址址,但是它还改变了TCP和UDP的格式:二个协议均为32 bit的端口号,64 bit的序列号,64 bit的确认号,以及TCP的32 bit窗口。
前三个建议基本上采用了相同版本的TCP和UDP作为传输层协议。
由于四个建议只能有一个被选为IPv4的替换者,而且在你读到此书时可能已经做出选择,因此我们对它们不进行过多评论。虽然CIDR即将实现以解决目前的缺期问题,但是IPv4后继者的实现则需要经过许多年。
3.11 小结
本章开始描述了IP首部的格式,并简要讨论了首部中的各个字段。我们还介绍了IP路由选择,并指出主机的路由选择可以非常简单:如果目的主机在直接相连的网络上,那么就把数据报直接传给目的主机,否则传给默认路由器。
在进行路由选择决策时,主机和路由器都使用路由表。在表中有三种类型的路由:特定主机型,特定网络型,默认路由型。路由表中的表目具有一定的优先级。在选择路由时,主机路由优先于网络路由,最后在没有其它可选路由存在时才选择默认路由。
IP路由选择是通过逐跳(hop-by-hop)来实现的。数据报在各站的传输过程中目的IP地址始终不变,但是封装和目的链路层地址在每一站都可以改变。大多数的主机和许多路由器对于非本地网络的数据报都使用默认的下一站路由器。
A类和B类地址一般都要进行子网划分。用于子网号的比特数能过子网掩码来指定。我们为此举了一个实例详细说明,即作者所在的子网,并介绍了变长子网的概念。子网的划分缩小了Internet路由表的规模,因为许多网络经常可以能过单个表目就可以访问了。接口和网络的有关信息通过ifconfig和netstat命令可以获得,包括接口的IP地址、子网的掩码、广播地址以及MTU等。
在本章的最后,我们对Internet协议族潜在的改进建议――下一代IP进行了讨论。
习题
3.1 环回地址必须是127.0.0.1吗?
3.2 在图3.6中指出有两个网络接口的路由器。
3.3 子网号为16 bit的A类地址与子网号为8 bit的B类地址的子网掩码有什么不同?
3.4 阅读RFC 1219 [Tsuchiya 1991],学习分配子网号和主机号的有关推荐技术。
3.5 子网掩码255.255.0.255是否对A类地址有效?
3.6 为什么你认为3.9小节中打印出来的环回接口的MTU要设置为1536?
3.7 TCP/IP协议族是基于一种数据报网络技术,即IP层,其它的协议族则基于面向连接的网络技术。阅读文献[Clark 1988],找出数据报网络层提供的三个优点。
3-1
4 ARP:地址解析协议
4.1 引言
本章我们要讨论的问题是只对TCP/IP协议簇有意义的IP地址。数据链路如以太网或令牌环网都有自己的寻址机制(常常为48 bit地址),这是使用数据链路的任何网络层都必须遵从的。一个网络如以太网可以同时被不同的网络层使用。例如,一组使用TCP/IP协议的主机和另一组使用某种PC网络软件的主机可以共享相同的电缆。
当一台主机把以太网数据帧发送到位于同一局域网上的另一台主机时,是根据48 bit的以太网地址来确定目的接口的。设备驱动程序从不检查IP数据报中的目的IP地址。
地址解析为这两种不同的地址形式提供映射:32 bit的IP地址和数据链路层使用的任何类型的地址。RFC 826 [Plummer 1982]是ARP规约描述文档。
本章及下一章我们要讨论的两种协议如图4.1所示:ARP(地址解析协议)和RARP(逆地址解析协议)。
图4.1 地址解析协议:ARP和RARP
ARP为IP地址到对应的硬件地址之间提供动态映射。我们之所以用动态这个词是因为这个过程是自动完成的,一般应用程序用户或系统管理员不必关心。
RARP是被那些没有磁盘驱动器的系统使用(一般是无盘工作站或X终端),它需要系统管理员进行手工设置。我们在第5章对它进行讨论。
4.2 一个例子
任何时候我们敲入下面这个形式的命令:
% ftp bsdi
都会进行以下这些步骤。这些步骤的序号如图4.2所示。
1. 应用程序FTP客户端调用函数gethostbyname(3)把主机名(bsdi)转换成32 bit的IP地址。这个函数在DNS(域名系统)中称作解析器,我们将在第14章对它进行介绍。这个转换过程或者使用DNS,或者在较小网络中使用一个静态的主机文件(/etc/hosts)。
2. FTP客户端请求TCP用得到的IP地址建立连接。
3. TCP发送一个连接请求段到远端的主机,即用上述IP地址发送一份IP数据报。(在第18章我们将讨论完成这个过程的细节。)
4. 如果目的主机在本地网络上(如以太网,令牌环网,或点对点链接的另一端),那么IP数据报可以直接送到目的主机上。如果目的主机在一个远程网络上,那么就通过IP路由选择函数来确定位于本地网络上的下一站路由器地址,并让它转发IP数据报。在这两种情况下,IP数据报都是被送到位于本地网络上的一台主机或路由器。
5. 假定是一个以太网,那么发送端主机必须把32 bit的IP地址变换成48 bit的以太网地址。从逻辑Internet地址到对应的物理硬件地址需要进行翻译。这个过程就是ARP的功能完成。
ARP本来是用于广播网络的,有许多主机或路由器连在同一个网络上。
6. ARP发送一份称作ARP请求的以太网数据帧给以太网上的每个主机。这个过程称作广播,如图4.2中的虚线所示。ARP请求数据帧中包含目的主机的IP地址(主机名为bsdi),其意思是“如果你是这个IP地址的拥有者,请回答你的硬件地址。”
图4.2 当用户输入命令“ftp 主机名"时ARP的操作
7. 目的主机的ARP层收到这份广播报文后,识别出这是发送端在寻问它的IP地址,于是发送一个ARP回答。这个ARP回答包含IP地址及对应的硬件地址。
8. 收到ARP回答后,使ARP进行请求-回答交换的IP数据报现在就可以传送了。
9. 发送IP数据报到目的主机。
在ARP背后有一个基本概念,那就是网络接口有一个硬件地址(一个48 bit的值,标识不同的以太网或令牌环网络接口)。在硬件层次上进行的数据帧交换必须有正确的接口地址。但是,TCP/IP有自己的地址:32 bit的IP地址。知道主机的IP地址并不能让内核发送一帧数据给主机。内核(如以太网驱动程序)必须知道目的端的硬件地址才能发送数据。ARP的功能是在32 bitIP地址和采用不同网络技术的硬件地址之间提供动态映射。
点对点链路不使用ARP。当设置这些链路时(一般在引导过程进行),必须告知内核链路每一端的IP地址。像以太网地址这样的硬件地址并不涉及。
4.3 ARP高速缓存
ARP高效运行的关键是由于每个主机上都有一个ARP高速缓存。这个高速缓存存放了最近Internet地址到硬件地址之间的映射记录。高速缓存中每一项的生存时间一般为20分钟,起始时间从被创建时开始算起。
我们可以用arp(8)命令来检查ARP高速缓存。参数-a的意思是显示高速缓存中所有的内容。
bsdi % arp -a
sun (140.252.13.33) at 8:0:20:3:f6:42
svr4 (140.252.13.34) at 0:0:c0:c2:9b:26
48 bit的以太网地址用6个十六进制的数来表示,中间以冒号隔开。在4.8小节我们将讨论arp命令的其它功能。
4.4 ARP的分组格式
在以太网上解析IP地址时,ARP请求和回答分组的格式如图4.3所示。(ARP可以用于其它类型的网络,可以解析IP地址以外的地址。紧跟着帧类型字段的前四个字段指定了最后四个字段的类型和长度。)
图4.3 用于以太网的ARP请求或回答分组格式
以太网报头中的前两个字段是以太网的源地址和目的地址。目的地址为全1的特殊地址是广播地址。电缆上的所有以太网接口都要接收广播的数据帧。
2个字节长的以太网帧类型表示后面数据的类型。对于ARP请求或回答来说,该字段的值为0x0806。
形容词hardware(硬件)和protocol(协议)用来描述ARP分组中的各个字段。例如,一个ARP请求分组询问协议地址(这里是IP地址)对应的硬件地址(这里是以太网地址)。
硬件类型字段表示硬件地址的类型。它的值为1即表示以太网地址。协议类型字段表示要映射的协议地址类型。它的值为0x0800即表示IP地址。它的值与包含IP数据报的以太网数据帧中的类型字段的值相同,这是有意设计的。
接下来的两个1字节的字段,硬件地址长度和协议地址长度分别指出硬件地址和协议地址的长度,以字节为单位。对于以太网上IP地址的ARP请求或回答来说,它们的值分别为6和4。
操作字段指出四种操作类型,它们是ARP请求(值为1),ARP回答(值为2),RARP请求(值为3),RARP回答(值为4)。(我们在第5章讨论RARP。)这个字段必需的,因为ARP请求和ARP回答的帧类型字段值是相同的。
接下来的四个字段是发送端的硬件地址(在本例中是以太网地址),发送端的协议地址(IP地址),目的端的硬件地址,目的端的协议地址。注意,这里有一些重复信息:在以太网的数据帧报头中和ARP请求数据帧中都有发送端的硬件地址。
对于一个ARP请求来说,除目的端硬件地址外的所有其他的字段都有填充值。当系统收到一份目的端为本机的ARP请求报文后,它就把硬件地址填进去,然后用两个目的端地址分别替换两个发送端地址,并把操作字段置为2,最后把它发送回去。
>> 相关资讯:
上一篇文章:TCP/IP远程访问操作 下一篇文章:TCP/IP详解(二)最新五条评论
查看全部评论
您的评论
·本站管理人员有权在不通知用户的情况下删除不符合规定的评论信息或留做证据
·请客观的评价您所看到的资讯,提倡就事论事,杜绝漫骂和人身攻击等不文明行为
内容搜索
最新更新文章
本类推荐文章



