linux高性能服务器编程 (二) --IP协议详解

时间:2024-08-30 15:05:02

第二章 IP协议详解

    什么是IP协议:IP 协议是TCP/IP协议族的动力,它为上层提供了无状态、无连接、不可靠的服务。

    IP 头部信息:头部信息会出现在每一个IP数据报上,便于记录IP通信的源端IP地址,目的端IP地址,指导IP分片和重组,以及指定部分通信行为。

    IP 数据报的路由和转发:除目标机器之外的所有主机和路由器上。它们决定数据报是否应该转发和如何转发。

    无状态:即每次的IP数据报发送、传输和接收都是相互独立的,没有上下文关系。缺点:无法处理乱序和重复IP数据报;优点:简单、高效。

    无连接:IP通信双方都不长久的维持对方的数据,所以每次发送数据的时候都需要带着指定对方的IP地址。

    不可靠:IP协议不能保证IP数据报准确地到达接收端。(如果某个路由器发现IP数据报在网络上存货时间过长,就会弃之。会返回一个ICMP的错误消息给发送端)

    IPv4的头部结构:

   linux高性能服务器编程 (二) --IP协议详解

   ipv4的头部信息从图片上可知,IP头部长度通常固定为20字节。其中重要的 16位总长度,它记录了IP数据报文的整个长度,最大长度可设置为65535字节,但是由于设置了MTU长度限制,所以,一旦IP数据报内容长度大于MTU的设置将进行分片传输。16位标识值是其默认的标识号,最开始是随机生成的,每发送一个数据报其值就会+1,所以对于分片操作,这个值就会被复制到每一个分片数据报的头部用来标识其分片是同一个数据包。3位标志字段的第一位属于保留字段,第二位标识禁止分片(DF),第三位标识多个分片(MF)。如果这个数据报分片了,那么除了最后一个分片其他分片3位标志要设置为1. 13位片偏移 是说明如果数据报偏大需要进行分片,那么分片的需要一个前后位置的区分,这个时候就需要偏移值去设置分片的位置,才能保证后面的IP分片拥有自己的偏移值。8位生存时间TTL就是数据报在到达目的地所经过的路由器跳数。虽然IP数据报请求过来经过广播转发路由器,但它不是一个死循环,它也是需要一个介质控制跳动的个数,而这个值就是它的介质。16位头部校验,是为了监测IP数据报在路由器转发的过程中是否有数据损失,其值是发送端设置的。当数据报到达目的地的时候,接收端使用CRC算法对数据进行校验。而32位源端IP和目的地IP地址则是发送端的IP地址和到达目的地的地址,所以这个在传输的过程中是不会变的。

  IP分片

  linux高性能服务器编程 (二) --IP协议详解

举个例子如上图:对于以太网帧的MTU是1500字节。对于IP数据报1501个字节来说就需要进行分片转发路由。对于第一个分片需要将其头部3位标志设置(mf)置为 1,而将最后一个 (mf)置为 0 。对于第一个分片去掉IP头部固定为长度为20个字节,那么剩余可存放的字节数为1480个字节。只要满足IP数据报的长度为1500字节即可,对于IP数据报1501个字节那么它的第二个数据报的长度为应该为21个字节(因为包含固定IP头部20个字节)。从图片中可了解,原始的IP数据报将头部数据复制成了第一个分片的头部信息,而第二个分片则不需要ICMP等多余的头部的信息(因为没必要在重复)。那么对于IP都是无连接、无可靠、无状态的性质来说,分片传递到目标端它们也是可以组合在一起的,这就通过上文描述的16位标识取组合在一起。那么如果第二个分片先到达目的地,也是可以和第一个分片组合在一起的,因为对于分片来说事先都已经设置好前文所说的13位片偏移,通过偏移值可以找到该分片应该处放的位置,直到遇到衔接的分片就会进行分片组合。

  IP路由 

  上文已经说了IP数据报的分片,将一个个小小的分片进行路由转发送达到目的地。没错,那么IP协议是如果进行选路由的呢?首先我们需要了解一下IP模块的工作流程。

  linux高性能服务器编程 (二) --IP协议详解

  根据上图从右->左的方式开始讲解。当IP模块接收到来自数据链路层的IP数据报时,首先通过CRC校验一下头部数据是否有损失,如果损失则发送一个ICMP的错误消息。如果ok则验证IP数据报的头部是否设置了源站选路,如果设置了则进行数据报转发流程,如果没有则发送给本机的数据报验证。在本机的数据报验证处需要判断是否是发送给本机的某个IP地址、如果不是发送给本机的那就是需要发送到上层网络层的某个IP地址则也调用数据报转发子模块来处理该数据报。而在数据报转发处需要验证该数据报是否允许转发,如果不允许转发则丢弃。否则会对该数据报进行一些操作,然后将它交给IP数据报输出子模块。

  这里略过转发路程,IP模块实现数据报路由的核心数据结构是路由表,这个表按照目标地址IP分类,同一类型的IP数据报将被发往相同的吓一跳路由器。IP的路由机制共分为三个步骤:1)查找路由表中和数据报的目标IP地址完全匹配的主机地址,如果找到就使用该路由表项,否则转向步骤2。2)查找路由表中和数据报的目的IP地址具有相同网络ID的网络IP地址,即是同一网段的IP地址,如果找到则使用该路由表项,否则转向步骤3。3)选择默认路由,通常意味着下一跳路由是网关。 

  路由表必须能够更新,才能让IP模块准确高效的转发数据报。路由表的变更可以通过手动变更,或者通过route命令变更,对于测试来说是常用的手段。但是对于大型路由器。它们通常是动态或自动更新的,主要由 BGP (边际网关协议) RIP (路由信息协议) OSPF 等协议来发现路径,并更新自己的路由表。

  除了发送给本机的IP数据报都会走到数据报转发子模块来处理。如果该数据报允许转发那么数据报转发子模块将对期望转发的数据报执行如下流程:1)检查数据报头部的TTL值,如果TTL值已经是0,则丢弃该数据报。2)查看数据报头部的严格源路由选择选项,如果该选项被设置,则检测数据报的目标IP地址是否是本机的某一个IP地址,如果不是则发送一个ICMP源站选路失败报文给发送端。3)如果有必要,则给源端发送一个ICMP重定向报文,以告诉它一个更合理的吓一跳路由器。4)将TTL值减 1.5)处理IP头部选项。6)如果有必要,则执行IP分片操作。

  从上图上可看到,还有一个ICMP重定向报文。在特定的情况下,当路由器检测到一台机器使用非优化路由的时候,它会向该主机发送一个ICMP重定向报文,请求主机改变路由。路由器也会把初始数据包向它的目的地转发。发生ICMP重定向通常有两种情况:1)当路由器从某个接口收到数据还需要从相同接口转发该数据时。2)当路由器从某个接口到发往远程网络的数据时发现源ip地址与下一跳属于同一网段时。