写点什么

万字图解 | 深入揭秘 IP 层工作原理

作者:云舒编程
  • 2024-01-25
    广东
  • 本文字数:5521 字

    阅读完需:约 18 分钟

万字图解 | 深入揭秘IP层工作原理

大家好,我是「云舒编程」,今天我们来聊聊计算机网络面试之-(网络层 ip)工作原理。


文章首发地址:云舒编程


前言

        想必不少同学在面试过程中,会遇到「在浏览器中输入www.baidu.com后,到网页显示,其间发生了什么」类似的面试题。


        本专栏将从该背景出发,详细介绍数据包从 HTTP 层->TCP 层->IP 层->网卡->互联网->目的地服务器 这中间涉及的知识。


        本系列文章将采用自底向上的形式讲解每层的工作原理和数据在该层的处理方式。

系列文章

图解 | 深入揭秘数据链路层、物理层工作原理

图解 | 深入揭秘IP层工作原理

图解 | 深入揭秘TCP工作原理

图解 | 深入揭秘HTTP工作原理

图解 | 深入揭秘Linux 接收网络数据包

图解 | 深入揭秘IO多路复用原理


通过上一篇文章每天5分钟玩转计算机网络-(数据链路层、物理层)工作原理的介绍,我们知道了数据链路层和物理层的基本工作原理。同时也知道了 mac 地址和 ip 地址的区别。


在上一篇只是简单引入了 ip 的概念。本篇将会详解对网络层(ip)进行介绍。

通过本文你可学到:

  1. ip 地址构成

  2. 公有 IP 地址和私有 ip 地址

  3. ip 路由原理

  4. ip 分片与重组

IP 基础知识

IP 是整个网络架构中的心脏,你的请求可以跨过大洋彼岸,准确的到达目的服务器,就是 IP 提供的能力。它实现了网络设备点对点通信。

IP 地址构成

        IP 地址(IPv4)由 32 位正整数构成,在计算机中采用二进制表示。但是为了方便记忆和查看,一般采用点分十进制进行书面表示。也就是将 32 位 IP 地址以每 8 位为组,共分为 4 组,每组以“.”隔开,具体格式如下:



        由于限制了 IPv4 由 32 位组成,那么 IP 最大可以表示的值为:2^32=4294967296,也就是最多允许 42.9 亿多台计算机进行网络连接。


这里肯定会有人有疑问了:按照现在的互联网发展,网络上的设备早就超过 42.9 亿多了,那为什么互联网还是在正常运行呢? 

其实这得益于两方面的技术:ipv6 和 NAT。后面会详解介绍

IP 地址的分类

        互联网初开之时,网络上的设备还没有这么多,42 亿多的 IP 地址显得非常充足。于是大佬们大手一挥,决定将 IP 地址进行三六九等区分,方便进行管理。


        IP 地址于是被分为了五类:A 类、B 类、C 类、D 类、E 类。


        同时还分为了网络号和主机号,网络号可以对比是小区,主机号可以对比是小区里的房间


网络号和主机号的划分是为了实现网络地址的层次化管理。通过将网络号和主机号分开,可以将一个大的 IP 地址空间分成多个子网,每个子网可以包含多台计算机。这样可以更好地管理网络资源。



A 类:第一位固定为 0,紧接着的 7 位为网络位,剩下的 24 位为主机位。


B 类:前两位固定为 10,紧接着的 14 位为网络位,剩下的 16 位为主机位。


....


其余类推。


所以 ip 是按照以下原则进行层次分配的:



上述的 ip 分配原则,具有明显的缺点:


  1. 资源无法合理分配

  2. A 类地址的主机位为 24 位,可以容纳 2^24=16777216 台主机。

  3. B 类可以容纳 2^16=65536 台主机。

  4. C 类可以容纳 2^8=256 台主机

  5. C 类网络的主机数不够用,A 类,B 类的主机有太多了。

  6. 同一网络号下的 ip 无法再次进行层次划分

  7. 无法组建超网

  8. 假设你拥有几个不同网络号的连续 ip 地址,你想把他们组合起来,形成自己的超级网络。但是由于网络号的固定划分方式,发现无法做到


于是人们开始放弃 IP 地址分类,采用任意长度分割 IP 地址的网络标识和主机标识。这种方式叫做 CIDR(无类型域间路由)。

CIDR(无类型域间路由)

a.b.c.d/x

CIDR 采用 a.b.c.d/x 的形式表示 IP,其中 /x 表示前 x 位属于网络号, x 的范围是 0 ~ 32,这使得 IP 地址更加具有灵活性。


例如:


203.183.224.0/24



CIDR 应用的初期,网络内部采用固定长度的子网掩码机制,也就是说,当子网掩码的长度被设置后,域间的所有子网掩码都得使用同样的长度。


但是假如一个公司的市场部有 100 台电脑,销售部有 70 台电脑,一般企业中会希望将不同的部门划分成为不同的网段,一方面为了安全,一方面是为了方便网络管理。


如果想用 c 类地址段分别给三个部门划分不同的网段,我们看到需要用到三个 c 类地址段,我们知道一个 c 类地址段里就有 254 个主机地址,而这里用到了三个 c 类地址段,就造成了 ip 地址浪费的情况,为了保证 ip 地址的高利用率,这时候我们用到了 vlsm(可变长子网掩码)。

可变长子网掩码(vlsm)

除了使用上诉 a.b.c.d/x 分割网络号主机号,还可以使用子网掩码的形式进行分割。


子网掩码仅具有一项功能,即将 IP 地址分为两部分,即网络地址和主机地址。子网掩码也是由 32 构成,子网掩码不能单独存在,必须与 IP 地址一起使用。


将 ip 地址跟子网掩码进行 and 运算,就可以得到 IP 地址的网络号。


例如图中 IP 地址为:203.183.224.1,子网掩码为:255.255.255.0。两者 and 运算得到:203.183.224.0。这就是该 IP 对应的网络号。同时子网掩码不为 0 的部分有 8 位,所以主机部分有 8 位可以进行分配。

变长子网掩码的应用

还是以上面的公司举例:


假设公司有一个 C 类地址:192.168.1.0 我们都知道这样一个 c 类地址段里有 256 个地址,接下来我们将这 256 个地址划分成两个不同的网段,一个给市场部,一个给销售部。


假设我们从 8 位主机位中借一位,当做内部网段的网络位:



那么市场部的网络号就是:11000000.10101000.00000001.0 0000000(后面 7 位可以分配给主机)


那么销售部的网络号就是:11000000.10101000.00000001.1 0000000(后面 7 位可以分配给主机)


那么相应的子网掩码就变为:11111111.11111111.11111111.1 0000000,表示为 10 进制:255.255.255.128


同样的,只要主机位有剩余的位可以借,市场部内部还可以继续划分为市场部一、市场部二。


通过这样的形式就可以把网络划分为不同的子网。

IP 路由控制

前面已经了解了 IP 的构成,接下来进入本章的重点:路由控制


再次回顾上一篇最后画的网络拓扑图:



补充:其中 A,D 的子网掩码都为 255.255.255.0


假设 A 现在要发消息到 D,也就是 192.168.0.1 要发消息到 192.167.0.1。


  1. A 根据自己的子网掩码计算自己的 IP 地址和 D 的 IP 地址,发现结果不一样,于是判断出 D 与自己不在同一个子网

  2. 根据规则,A 会将消息发送给默认网关,然后由默认网关进一步判断下一步发给谁

  3. A 通过 ARP 协议获取默认网关的 mac 地址,然后封装消息发送给网关,消息格式:



  1. 默认网关(一般是路由器),收到请求后会根据自己路由表判断下一步该发给谁(可能是路由器,也有可能是交换机)

  2. 如果继续发给了路由器,那么路由器会继续跟进自己的路由表判断下一步发给谁,通过接力的形式转发到目的地

  3. 如果发给了交换机,那么交换机将会直接广播给全部主机

默认网关

默认网关是提前配置好的一条路由规则,存储在路由表中,一般使用 default 标识。


默认网关一般情况下由路由器担当。


A 的默认网关必须跟 A 在同一个子网,D 的默认网关必须跟 D 在同一个子网。但是 A 的默认网关可以不跟 D 的默认网关在同一个子网



通常情况下,默认网关的 IP 地址就是直接连接的路由器的某个端口的 IP 地址。


一般情况下,当主机发现目的 IP 跟自己不是同一个子网时,就会把消息发给默认网关,由默认网关进行下一步处理。

ARP 协议

        前面说到,A 发送消息给默认网关时,需要知道默认网关的 mac,但是路由表中只有 ip 地址,该怎么获取 mac 地址呢?这就是 arp 协议的作用了。


        当 A 需要知道某个 ip 的 mac 地址时,他就会广播 arp 消息:ip=xxx 的 mac 地址是多少啊。当同一个子网上的设备收到消息后会判断 ip 与自己是否一致,一致的话就会响应消息:我的 mac 地址是 xxx

路由表

当 A 把消息发送给路由器后,路由器怎么知道把消息发送给 D 呢?


这就是路由表的功能了。


路由表是一个存储在路由器或者联网计算机中的电子表格(文件)或类数据库。它存储了网络周边的拓扑信息。他为路由器指明了怎么把收到的消息包正确发送出去。

格式

路由表主要由以下几部分组成:


路由规则

假设有如下路由拓扑:



A 现在要发消息到 D,也就是 10.1.1.30 要发消息到 10.1.2.0。


  1. A 根据自己的子网掩码计算自己的 IP 地址和 D 的 IP 地址,发现结果不一样,于是判断出 D 与自己不在同一个子网

  2. 根据规则,A 会将消息路由器 1(默认网关)

  3. 路由器 1 根据最长 IP 匹配原则,发现 10.1.2.10 跟 10.1.2.0/24 前缀匹配匹配上的长度最长,于是选择


这条路由规则将消息从端口 2 发送给 10.1.2.1(路由器 2)


  1. 路由器 2 收到消息后同样根据最长 IP 匹配原则,发现 10.1.2.0/24 前缀匹配匹配上的长度最长,于是选择


这条路由规则将消息从端口 2 发送给 D

路由表是怎么生成的

静态路由

静态路由一般就是手动配置的,可管理性高。


缺点:


1、如果网络特别庞大、设备数量特别,配置的工作量就相当大了,这是很低效的;


2、静态路由无法根据网络拓扑的变更做出动态响应,因此当网络发生变化时,管理员可能不得不重新配置或调整静态路由。


所以静态路由一般很少使用。这里我们也不做讲解。

动态路由

动态路由可以根据特定的算法策略,通过路由器之间不断地交互信息,从而建立和更新自己的路由表。可以更好的适应网络变化


目前比较常用的是:基于链路状态路由算法的 OSPF(Open Shortest Path First,开放式最短路径优先)


它把链路状态信息的获取分成了 4 个主要步骤:


  1. 发现节点

  2. 当一个路由器启动的时候,使用单播(Unicast)和组播(Multicast)来发送 Hello 包。收到这条消息的节点必须回应一条 Response 消息,告知自己是谁。

  3. 每个节点只要统计自己发出 hello 后收到的回应数量,就可以知道自己和哪几个节点相邻,也知道了它们的地址之类的信息,保存在本地就可以了。

  4. 测量链路成本

  5. 现在每个路由器都有了自己的邻居信息,接下来要做的就是衡量边权也就是链路成本。

  6. 每个节点向自己的邻居发送一个特殊的 echo 包,邻居收到之后,必须原封不动地把 echo 再返回给发出 echo 的节点,这样,每个节点只需要统计一下自己从发出 echo 到收到 echo 的时间差,然后取多次的平均值,就可以用它来估计和邻居之间的网络传输时延了(RTT),从而也就可以计算出链路状态算法所需要的链路成本了。

  7. 封装链路状态包

  8. 每个路由器都知道自己到所有邻居节点的链路成本了,现在只要每个路由器把自己收集到的信息广播出去,同时也尽快收集别人的信息,就可以拼接出整个路由的拓扑图。

  9. 状态链路包格式:


  1. 发送链路状态包

  2. 泛洪:计算机网络中常用的一种传播消息的机制,类似广播,每个节点都会把自己封装好的包和收到的包,发送或转发给所有除了该包发送方的节点。

  3. 这样,经过一小段时间的传播,每个节点就可以收到整个网络内所有其他节点的邻居信息,从而也就相当于有了一个拓扑图中邻接表的全部信息,就可以在内存中构建出一张完整的路由表了。



  1. 计算路由

  2. 根据收集到的信息,使用 Dijkstra 算法,在有向图中计算出自己到网络中任何其他所有节点的最短路径。


A的最短路A->BA->B->DA->B->D->EA->B->D->E->FA->C
复制代码


A的路由表Destination Gateway      B          B    C          C    D          B    E          B    F          B
复制代码

IP 报文分片与重组

        类似我们在日常生活中寄快递,如果我们的东西非常多,那么会把东西分别打包成几个包裹再进行寄送。


        在网络中也是一样的,受限于光缆和路由器内存限制,所以单个数据数据包不能过大,过大时需要分割成几个数据包再进行发送。

MTU

  1. MTU 规定了每种数据链路的最大传输单元,类似我们最常见的以太网 MTU 就是 1500 字节。

  2. 那么当 IP 数据包大小大于 MTU 时, IP 数据包就会被分片。数据包分片可以在主机或者路由器进行,但是重组只能在主机进行。

  3. 假设需要发送 4342 字节的数据,由于 MTU=1500,那么数据包就会被分割成 3 个数据包发送出去

分片与重组过程

IP 报文的首部格式如下:



其中以下三个字段控制 IP 分片重组



  1. 标识(identification)占 16 位。

  2. IP 软件在存储器中维持一个计数器,每产生一个数据报,计数器就加 1,并将此值赋给标识字段。但这个“标识”并不是序号,因为 IP 是无连接服务,数据报不存在按序接收的问题。当数据报由于长度超过网络的 MTU 而必须分片时,这个标识字段的值就被复制到所有的数据报片的标识字段中。相同的标识字段的值使分片后的各数据报片最后能正确地重装成为原来的数据报

  3. 标志(flag)占 3 位。

  4. 标志字段中由三部分组成(保留+DF+MF):但目前只有最后两位有意义。

  5. MF=1 即表示后面“还有分片”的数据报。

  6. MF=0 表示这已是若干数据报片中的最后一个。

  7. 标志字段中间的一位记为 DF(Don't Fragment),意思是“不能分片”。只有当 DF=0 时才允许分片。

  8. 片偏移,占 13 位。表示一个分片相对于原始 IP 包开头的偏移量,以 8 字节为单位;这就是说,每个分片的长度一定是 8 字节(64 位)的整数倍,最后一片除外。

分片

还是以前面说的为例:假设需要发送 4342 字节的数据,由于 MTU=1500,那么数据包就会被分割成 3 个数据包发送出去。



分片一:包含原包前 1480 字节数据,因此偏移量 offset=0 ,而 MF=1 表示后面还有其他分片。


分片二:包含原包紧接着的 1480 字节数据,偏移量 offset=1480/8=185 ,MF=1 ;


分片三:包含原包最后 1381 字节数据,偏移量 offset=(1480+1480)/8=370 ,MF=0 表示它是最后一片了。

重组

目标主机操作系统会分配一块内存作为重组分片的缓冲区,缓冲区存在多个队列。


  1. 分片达到后,系统根据(标识、源地址、目标地址、协议)计算出 hash 值,判断该 hash 值对应的队列是否存在,存在则把数据放入该队列,不存在则新建队列后再放数据。

  2. 根据报文的片偏移值将报文插入到分片队列中合适的位置。

  3. 判断报文是否全部到达

  4. 片偏移=0,代表第一个分片报文已经到了,INET_FRAG_FIRST_IN

  5. MF=0,代表最后一个分片报文已经到了,INET_FRAG_LAST_IN

  6. 所有报文数据部分的长度之和是否等于 ip 头部中的总长度-首部长度

  7. 校验报文是否完整

  8. 投递给上层

结尾

经过 ip 层的补充讲解,现在我们的网络分层长这样了,接下来我们需继续讲解 TCP 层。


推荐阅读

1、原来阿里字节员工简历长这样

2、一条SQL差点引发离职

3、MySQL并发插入导致死锁


如果你也觉得我的分享有价值,记得点赞或者收藏哦!你的鼓励与支持,会让我更有动力写出更好的文章哦!


发布于: 3 小时前阅读数: 5
用户头像

云舒编程

关注

公众号 云舒编程,大白话分享技术原理 2020-09-23 加入

字节、阿里资深工程师。 做过营销、支付、百万级Feed流优化、权限系统、网关。 专注于技术原理分享,用最简单的话分享最复杂的技术原理

评论

发布
暂无评论
万字图解 | 深入揭秘IP层工作原理_IP_云舒编程_InfoQ写作社区