8 个问题搞懂网络三层:数据包是如何从一台设备发到另一台的?

0 阅读10分钟

本文仅用于学习记录,具体内容请参考
www.bilibili.com/video/BV17x…
mp.weixin.qq.com/s/N8a-YcCoV…
通过学习完这个视频,可以更好地理解
三层(物理层、数据链路层、网络层)
三表(MAC映射表、路由表、arp缓存表)
三设备(电脑、交换机、路由器)
能够自己描述清楚数据包是如何封装和传递的。

1 多个设备之间如果需要通信,如何实现?

最简单的办法就是如下图所示,各个设备之间通过网线相连。但是当设备多起来之后,就会变得非常的混乱。自然引出第二个问题。 image.png

2 我们如何解决混乱的一对一网线的连接?(物理层)

集线器应运而生,我们将所有网线插在集线器上,然后用集线器做转发。如下图所示,地址A想要将数据发送给地址B,那么包的开头会带有源地址和目的地址。集线器会将数据包发送给B/C/D/E所有的设备,然后会有一个关键过滤——所有终端设备(PC、手机、服务器等)的网卡(NIC)都有的一个核心功能:实时监听收到的数据包,并校验 “目的 MAC 地址” 是否与自己的 MAC 地址匹配
这个校验是 “硬件级” 的(由网卡芯片完成,不占用 CPU 资源),是网卡硬件层面的默认行为,而非操作系统或软件层面的 “可选操作”。
这样我们就初步解决了一对一的繁琐的网线连接。
由于集线器只是无脑将电信号转发到所有出口(广播) ,不做任何处理,由此物理层便定义好了。
但现在我A这台设备发给B的数据包会发送给所有设备,这是我不想见到的,这里引出第三个问题。
image.png

3 如何保证源地址发送的数据包只发向我们想要的目的地址(数据链路层)

交换机就被发明了出来。交换机相比集线器会智能一些,它内部维护了一张MAC地址表,其中记录了各个设备的地址对应的交换机端口号,这样当A想要发送数据包给B的时候,一查表就知道数据包要从5号端口出了。
交换机只会把数据包发送给目的地址,比集线器更加智能,至此数据链路层定义好了。(包前面加上的包头 源mac和目标mac可以看作是数据链路层头部。)
需要注意的是,这张MAC地址表最开始是空的,交换机通过泛洪机制,将原始数据包复制到 “除接收端口外的所有物理端口”,然后记录下能够通过硬件校验的端口号,这样就逐步的将这张MAC地址表给完善起来了。
但随着网络中电脑的数量越来越多,交换机的端口逐渐不够用了,从而引出第四个问题。
image.png

4 如何应付日益增多的电脑数量?(网络层)

最简单的想法:如下所示,将多个交换机连接起来,就能扩展端口数量,从而实现多台电脑之间的正常通信。
image.png 但是MAC地址端口映射表中必须存有所有的电脑MAC地址,这是不现实的。如下所示,红色线发送出的所有链路都需要记录在映射表中。几百台设备还能接受,成千上万台设备,这个表就不能有效维护了。 image.png 因此,我们又想到了另一个方法,用一台独立的设备替代红色的网线,该设备具有独立的MAC地址,能够帮我们把数据包做一次转发
这个独立的设备就是路由器,路由器的每一个端口就是一个独立的MAC地址。
如下图所示,有了路由器,就能解决两个棘手的问题
① 首先每个交换机的MAC端口映射表就不需要再有那么多项了,例如交换机1的端口6 只需要对应路由器的MAC地址ABAB就行了。
② 其次,我们如果想把数据从A发送到C或D,只需要将C和D的MAC地址设置为FFFF-FFFF-CCCC和FFFF-FFFF-DDDD。这样交换机1只要看到前缀是FFFF-FFFF,交换机就知道得发往路由器了
image.png
但在实际的处理中,将MAC的前缀这样设置是不可能的。
这是因为MAC 地址在世界是唯一的,一共48位。其中前24位代表网络硬件制造商的编号,后 24 位是该厂家自己分配的,一般表示系列号。
我们无法做到设置网络时,固定每个交换机所负责的区域内都是我们想要的FFFF-FF(24位,网络硬件制造商)厂家生产的产品FF-XXXX(24位,产品序列号)。所以,这里就引入了下一个问题。

4.1 如何定义不同的交换机区域的地址前缀呢?(IP地址)

我们发明了一套区别于MAC的新地址,给每一台机器一个32位的编号,这就是IP地址,如下所示
11000000.10101000.00000000.00000001
我们还可以用10进制来表达
192.168.0.1
由于IP地址是软件层面的,可以随时修改,那么我们就可以用IP地址来定义不同交换机区域的地址前缀了。例如我们将一个区域内的所有机器的IP地址都设置为192.168.xxx.xxx,那么我们只需要将地址为192.168开头的全部发送到路由器端口,再由路由器转发就行了。
下面我将举一个具体的例子,详细说明路由器是如何转发数据包的。
image.png
值得注意的是,数据链路层中,数据包已经有了数据链路层头部。而当IP地址引入时,数据包已经有了网络层头部
如果A直接发送数据包到B,他们连接在同一个交换机上,不涉及路由器。那么他们的数据包封装如下所示:
image.png
但如果A需要发送数据包到C,那么就需要经过路由器的转发,
① A->路由器
image.png
② 路由器->C
image.png
这样数据就由A发送到了C。
这里有一点需要明确的是,并不是有了IP地址之后,数据包发送时,就不需要MAC地址了。恰恰相反,
网络层(IP协议)本身没有传输包的功能,包的实际传输是委托给数据链路层(以太网中的交换机)来实现的!!!
而MAC地址其实A最开始并不知道,也就是说A发送数据包到C,A知道C的IP地址,但其实不知道C的物理MAC地址是什么。A是通过查找本地的arp表查询得到的!arp表中存放有IP地址与MAC地址的映射关系,如下所示

IP地址MAC地址
192.168.1.1CCCC

数据包传输时,是必须知道每个目的节点的MAC地址的!!!
但是这就有了一个问题,我们是从上帝视角知道A直勾勾地往路由器走,再往C走。那么数据包是如何只通过数据链路层头部和网络层头部的封装知道,从A发往C,需要从交换机的哪个端口发出呢?

4.2 A给C发数据包时,交换机如何确定是否发向路由器?(子网)

其实对应的原则很简单——如果源IP与目的IP不处于一个子网中,直接将数据包发送到路由器所对应的端口。
那么怎么才算在一个子网中呢?
每台机器都有自己的子网掩码,例如A机器的子网掩码是255.255.255.0。那么A机器会将源IP与目的IP分别同这个子网掩码进行与运算,相同则是在一个子网,不相同就是在不同子网。 还是以上面一个图为例,
A给C发消息,源IP为192.168.0.1,目的IP为192.168.1.1.
192.168.0.1 & 255.255.255.0 = 192.168.0.0
192.168.1.1 & 255.255.255.0 = 192.168.1.0
两者并不相同,所以A给C发数据包时,就知道二者不在同一个子网中,所以交换机就知道直接将数据包从路由器对应的端口发出就行了
但是,这就引出了第7个问题。

4.3 A怎么知道路由器在哪里呢?(默认网关)

很简单,路由器有自己的IP地址192.168.0.254。 每个机器在自己内部配置了一个默认网关,即同一个子网下的路由器IP地址。这样A就能顺利的找到路由器了。 image.png
此时数据顺利地发送到了路由器,那路由器怎么知道数据从哪个端口发送出去呢?

4.4 路由器如何知道发往C的数据包应该从哪个端口发出?(路由表)

这个问题其实很容易想到,路由器内部肯定也维护了一张地址表,类似于MAC地址表。
事实也确实如此,只是这张表不叫作MAC地址表了,而叫做路由表
路由表中记录了每个子网应该从哪个端口发出,如下所示:

目的地址端口
192.168.0.0(24)0
192.168.1.0(24)1

括号中的数字代表了前多少位表示子网的网段,因此当目的地址为192.168.1.1时,路由表就知道数据包需要从端口1发出了,最终数据包就成功地从A发送到C了。

5 总结

现在经过8个问题我们就知道了数据是如何包装发送的了,这里我们再重新简单复习一遍数据包的发送流程。

  1. 首先发送数据时,我们需要知道当前设备的源IP地址和目的IP地址。

  2. 通过子网掩码(例如255.255.255.0)判断源IP和目的IP的设备是否在同一个子网下。

  3. 如果在同一个子网下,
    ① 通过arp表获取目标MAC地址往交换机发送
    ② 交换机收到数据包后检查是否有MAC地址,通过MAC映射表查找映射关系,如果查询到,那么就从交换机的指定端口发送给目标设备
    ③ 目标设备收到数据包

    如果不在同一个子网下,
    ① 通过arp表获取默认网关的MAC地址往交换机发送
    ② 交换机收到数据包后检查是否有MAC地址,通过MAC映射表查找映射关系,如果查询到,那么就从交换机的指定端口发送给路由器(因为是默认网关的MAC地址) ③ 路由器收到的数据包后,检查是否有目标IP地址,然后通过路由表查映射关系,查到了就从指定端口发送给目标设备。
    ④ 目标设备收到数据包。

经过以上内容的复习,我们已经理解了数据包是如何发送数据的。
并且从网路设计的层面通过提问的方式,“提出”并理解了
物理层(把比特变成信号传输)、
数据链路层(可靠地传输数据包)、
网络层(找路径+转发数据包,让数据包找到自己应该往哪里跳)
至此,通过这三层协议,我们已经能够实现将数据包从地球上任何一个位置发往另一个位置了。