IP协议直接位于2层数据链路层之上,负责生成发往目的地的数据报。IP协议原来在RFC 791中定义,后来进行了修改并且进行了多次重新修订。但是,IP协议的基本设计思想仍没有变。IP层不提供任何类型的流量控制或者排序功能。这些功能留给上层。我们将使用“数据报” (datagram)这个词汇指一个完整的IP信息,使用“数据包”(packet)这个词汇指一个单个的IP数据包。
IP协议负责接收和发送指定IP地址数据包。但是,IP协议并不保证数据传递的可靠性。在IP协议层中没有“重试一下”的概念。由于各种原因,数据包有可能出现丢失、损坏、重复、不按照顺序传递或者延迟等问题。IP协议还负责处理IP选项并且以ICMP错误和控制消息等方式提供反馈信息。
IP数据报头有20个字节长,紧接在2层报头后面(因为IP协议是第3层协议)。IP数据部分包含一个完整的TCP或者UDP数据包等一切其它的信息,如下面的图表所示。还要指出的是,如果使用IP选项,IP数据报头可以超过20个字节。
以太网报头
|
IPv4包头
|
数据(TCP等)
|
IP协议的目标很简单:生成发往目的地的数据报,而且除了把这个数据包发送到下一跳路由器之外,不需要担心任何事情。实际上,IP协议很复杂,否则,IP数据报头就不需要那么多的字段。认真研究IP数据报头是非常重要的。这些字段从第一个字节开始的含义是:
•版本:使用的IP协议的版本。IPv4数据包将把这个字段设置为“4”。
•报头长度:以4个字节的倍数的方式说明报头的长度。因为很少使用IP选项功能。因此,你很可能你看到它的值将是“5”,意味着报头的长度是5个4字节,也就是20个字节。
•服务类型:这个字段很少使用。但是,在理论上,这个字段旨在向路由器提供转发队列中特定IP数据报优先级顺序信息。主要用于提高服务质量。主机可以选择设置各种选项,如低延迟、高数据吞吐量或者高可靠性等。大多数路由器都忽略这些选项。
•总长度:以字节为单位具体说明包括报头在内的整个IP数据包的总长度。因为这个字段有16位,所以IP数据包长度限制在65K之内。这个数字定义的是字段所在的IP数据包,而不是整个IP数据报的长度。
•IP数据报ID:有时候称作“段标识符”。这个标识符用来确定一个具体的IP数据包属于哪一个IP数据报。如果IP协议需要把多个单个的IP数据包组合成一个IP数据报,这个字段是必要的。
•标志:DF(不分片)位在这个字段中用来指示路由器不要把IP数据包分段。这里也可以使用MF(更多地分片)标识。
•段内偏移量:原来数据报中的分段的偏移量,用64位的块表示。
•生存时间(TTL):IP数据包在被销毁之前包含的跳数。生存时间是为了避免无法发送的数据包永远在互联网上流动。
•协议类型:具体指明下一个协议。也就是在IP数据包的数据部分中将遇到的报头。
•头校验和:一个报头的校验和,而不是数据的校验和。
•IP源:原来发送数据包的主机的IP地址。
•IP目的地:IP数据包目的地主机的IP地址。
当路由器收到一个IP数据包的时候,路由器首先要检查这个数据包的目的地。如果这台路由器有一个通向目的地的路由,这台路由器将减少这个数据包的TTL,重新计算校验和,然后再把这个数据包发出去。如果出现错误,将会发出相应的ICMP错误通知,这个数据包将被丢弃。IP协议就是以这种最简单的方式工作的:它遇到每一个数据包都要重复上述的步骤。IP分段对于IP功能是非常重要的,它提供了这些报头字段的真正含义。并非每一个发送数据包的物理网络都能够接受同样大小的数据包。各种各样的2层帧格式允许同时发送不同大小的数据。允许的最大的MTU是65KB,最小的是68字节。RFC 1122规定,所有的主机必须能够重新组合最多为576字节的数据报,但实际上是应该能够重新组合与系统接口的MTU规格相同的数据报。
当在互联网上发送一个IP数据报的时候,你不知道沿着每一个2层链路前进的MTU将发生什么情况。你可能通过以太网连接自己的ISP。但是,你正在设法访问的远程站点也许是在一个ISDN链路上。因此,你的IP数据包在到达最后一个跳点之前必须要分段。分段可能需要进行多次。如果我们要向一个通过ISDN连接的远程站点发送一个2000个字节的数据包,我们原来可能把这个数据包分段以便符合我们的1500个字节的链路要求。但它大于576字节(ISDN的MTU)。因此,在到达ISDN链路之前的最后一个路由器必须还要对这个数据包分段。
应该知道,IP不是一个可靠的协议。因此,如果任何IP分段在传输的路径中丢失,整个数据报必须要重新发送。IP没有办法要求得到数据报中丢失的特定部分。因此,当出现错误时,其结果是重新发送该数据报所有的分段。有时候,阻塞的路由器不得不丢弃一些数据包。如果被丢弃的数据包恰巧是一个65KB数据报的一部分,那么,整个数据报必须要重新发送。TCP或者其它上层协议一般都知道一个完整的数据报是否全丢失了,并且能够要求重新发送。然而,TCP协议不能告诉你一个数据报的片段是否丢失了,因为IP收到数据报将是不完整的,并且永远不会向上层TCP协议发送这个数据报。如果TCP协议从来没有收到这个数据报,这个数据报最终将被重新发送。显然,65K数据包的一小部分的丢失对于缓解一个阻塞的链路并没有什么帮助,而是会引起更严重的阻塞。UDP应用程序发送时的大小一般不超过576字节,这有两个原因。第一,MTU小于576字节的链路并不多,因此,这个IP数据报将不会分段。第二,要记住,576是所有采用IP协议的端点系统的特殊数字:它们必须能够把数据报重新组合为这个大小。配置有限内存的设备对于处理大于这个规格的数据可能会遇到困难,因此,这个做法值得推荐。
假设我们是一台主机,我们想发送一个1550个字节的数据报(1530个字节的数据+20个字节的报头)。但是,我们的MTU是1500个字节。我们必须要分为两个数据包发送,相关的IP报头看起来是这样的:
• fragment 0, offset = 0, size = 1480, MF位设置.
• fragment 1, offset = 1480, size = 50
分段中的IP ID和IP地址总是与原来IP数据报中内容是一样的。但是,报头的校验值、偏离量和字段长度肯定要发生变化。当另一方收到第一个数据包并且看到这个数据包是一个分段的时候,另一方将等待获得其它的分段,并且把这些分段重新组合在一起,然后再发送给上层协议。
在这个数据报发出之后,假如在IP标志中没有设置DF字节,我们就不会听到任何有关这个数据报的消息。但是,如果这个链路的某一个地方的MTU是400字节会发生什么情况呢?在可以发送1480字节的数据包之前,这个链路中的路由器会先对这个数据包分段。上一篇教程的MTU路径可用来解决中间路由器为数据包分段的问题。分段要耗费时间和宝贵的路由器资源。我们避免过度分段的主要原因就是因为过度分段将不可避免地引起通信的延迟。
对数据包的重新组合总是在最后的目的地完成。因此,中间路由器不需要存储IP数据报。这也意味着IP数据包能够在不同的路径上单独地路由,而不会引起混乱。这是一个需要理解的重要的概念。这将使IP协议有多种用途。无论接收方以什么顺序收到这个数据包,接收方都能够根据IP报头中的分段偏移量字段重新把数据报组合起来。
现在,我们理解了分段。我们发现分段提出了这样一个问题:IP真的与数据链路层无关吗?
小结
IP协议是不可靠的。当IP数据包丢失的时候,要更高一层的协议认识到数据包的丢失并且要求重新发送。
路由器在每一次发送IP数据包的时候都必须要重新计算IP报头的校验值。
IP分段能够让路由器延迟发送一个数据包或者在多个链路上发送数据包。端点系统将能过重新组合整个IP数据报。