各层(物理层、数据链路层、网路层)设备的作用

@[toc] --- 一定要记住下面这句话!!! **网络层(IP 协议)本身没有传输数据的功能,数据的实际传输是委托给数据链路层(以太网中的交换机)来实现的,网络层起指导作用,指导数据在数据链路层到底该怎么走** ## 物理层 - 集线器(一层设备) 它仅仅是**无脑将电信号转发到所有出口(广播),不做任何处理**。目标主机在收到数据包后,根据头部的目标 MAC 地址信息,判断这个数据包是否是发给自己的,如果是便收下,否则抛弃 如上图所示,集线器连着 A B C D E 五台计算机,其中,A 计算机对应端口 1, B 计算机对应端口 3,C 计算机对应端口 7…… 假设 A 想要给 C 发个消息,那么集线器会将 A 的消息广播给所有的计算机,由各个计算机自己判断是不是发送给自己的消息。 <img src="https://cs-wiki.oss-cn-shanghai.aliyuncs.com/image-20230324124100952.png" style="zoom: 50%;" /> ## 数据链路层 - 交换机(二层设备) 虽然集线器使整个布局干净不少,但原来我只要发给电脑 B 的消息,现在却要发给连接到集线器中的所有电脑,这样既不安全,又不节省网络资源。如果把这个集线器弄得更智能一些,**只发给目标 MAC 地址指向的那台电脑**就好了,这就是交换机 > 所以说**集线器是一种过时的技术** ![A 通过交换机给 C 发送消息](https://cs-wiki.oss-cn-shanghai.aliyuncs.com/image-20230324124149424.png) 那具体是怎么做到的呢? 事实上,交换机内部维护一张 【**MAC 地址表**】,记录着每一个 MAC 地址的设备,连接在哪一个端口上。 - 如果发来的包首部中包含的目标 MAC 地址在地址表中并**没有**映射关系,交换机就将此包广播给所有端口,也即发给了所有机器; - 如果地址表**有**映射,那就只发给那一个端口 比如 A 想要给 C 发送消息,一开始交换机的 MAC 地址表是空的,交换机并不知道 C 的端口号,因此 A 发送的消息将会被广播,同时,A 的 MAC 地址和它对应的端口号会被记录到 MAC 地址表中。 ![A 通过交换机给 C 发送消息,此时 MAC 地址表为空](https://cs-wiki.oss-cn-shanghai.aliyuncs.com/image-20230324124212692.png) 这样,C 对 A 的消息进行响应的时候,交换机就不需要进行广播消息了,并且,C 的 MAC 地址和它对应的端口号会被记录到 MAC 地址表中。 ![C 通过交换机给 A 发送消息,此时 MAC 地址表中含有 A 的信息](https://cs-wiki.oss-cn-shanghai.aliyuncs.com/image-20230324124236358.png) ## 网络层 - 路由器(三层设备) 交换机似乎看起来已经是最优解了,但事实上,随着计算机设备越来越多,交换机的端口都不够用了,当然你肯定能想到可以用将多个交换机互相连接起来,然后每个交换机之间都互相共享他们的 MAC 地址表。但随着计算机数量的增长,比如 10 亿台设备,100 万个交换机,那这 100 万个交换机都需要各自维护包含 10 亿条记录的 MAC 地址表,无论是从经济还是效率上来说这也都不是一个很好的选择。 所以将交换机连接在一起这个思路确实没有错,但不能粗暴的直接连接在一起,得想个办法,让每个交换机仍然只需要维护和自己连接的设备的 MAC 地址表,同时还能和其他交换机进行共享 路由器应用而生。 路由器同样有很多端口,每一个端口都拥有一个 MAC 地址和一个 IP 地址,每一个端口都连着一个局域网(或者说子网或者说 IP 地址段也行,本文就不过多区分子网和局域网的含义了)或者另一个路由器 举个简单的例子,有两个子网,每个子网内都只有一个交换机,交换机上连接着若干个计算机设备,用路由器把这两个交换机连接起来,当两个子网之间需要进行通信的时候,通过路由器就可以实现了。 <img src="https://cs-wiki.oss-cn-shanghai.aliyuncs.com/image-20230324124307519.png" style="zoom:60%;" /> 那具体是怎么做到的呢? 事实上,路由器内部同样维护着一张表,这张表称为【**路由表**】,记录着每一个局域网(IP 地址段)和它对应的端口。 比如某个路由器的端口 0 上连接着 `192.168.0.x` 的 IP 地址段,端口 1 上连接着 `192.168.1.x` 的 IP 地址段,那么路由表就是下面这样: | 目的地址 | 端口 | 下一跳 | | -------------- | ---- | ------ | | 192.168.0.0/24 | 0 | | | 192.168.0.1/24 | 1 | | 大伙一定发现了上面路由表中还有 ”下一跳“ 这个字段,很简单,一个路由器的端口毕竟是有限的,不可能一个路由器连接所有的 IP 地址段,因此,如果该路由器发现目标计算机的 IP 地址不在自己管辖的 IP 地址段之内,就会通过下一跳地址转发给其他的管辖这个 IP 地址的路由器 路由器具体是怎么工作的呢?比如 A 给 C 发送数据,A 在子网号为 `192.168.0.x` 的子网,而 C 在子网号为 `192.168.1.x` 的子网,那么 **A 首先需要知道 C 和自己是不是在同一个子网**: - 如果**是**同一个子网,那么直接把数据发送给交换机就可以了 - 如果**不是**同一个子网,那么需要经过路由器的转发,A 需要把数据通过交换机发送给路由器,然后由路由器决定该发送给哪个子网 <img src="https://cs-wiki.oss-cn-shanghai.aliyuncs.com/image-20230324124521517.png" style="zoom:50%;" /> 这里有两个问题: 1)**A 如何判断是否和 C 在同一个子网?** 答案:这个简单,也不是本文重点,不过多介绍了,就是将源 IP 与目的 IP 分别同子网掩码进行与运算,结果相等就是在同一个子网 2)**A 如何知道哪个设备是路由器?** 答案:每个计算机上都要设置【默认网关】 其实说发给路由器不准确,应该说 A 会把数据包发给默认网关。 对 A 来说,A 只能直接把数据包发给同处于一个子网下的某个 IP 上,所以其实发给路由器还是发给某个计算机设备,对 A 来说并没有什么区别,反正它只认得 IP 地址。 所以默认网关,其实就是 A 在自己电脑里配置的一个 IP 地址,以便在发给不同子网的设备时,发给这个 IP 地址。 ![路由表示例](https://cs-wiki.oss-cn-shanghai.aliyuncs.com/image-20230324124537704.png) ## 总结 如下图 A 给 F 发送一个数据包,我们来梳理下整个通信过程: ![](https://cs-wiki.oss-cn-shanghai.aliyuncs.com/image-20230324124556957.png) 1)首先 A(`192.168.0.1`)通过子网掩码(`255.255.255.0`)计算出自己与 F(`192.168.3.2`)并不在同一个子网内,于是决定发送给默认网关(`192.168.0.222`) 2)A 通过 ARP 协议找到 默认网关 `192.168.0.222` 的 MAC 地址(数据链路层需要知道 MAC 地址才能传输数据) 3)A 将源 MAC 地址(`AA-AA-AA-AA`)与网关 MAC 地址(`MM-MM-MM-MM`)封装在数据链路层头部,又将源 IP 地址(`192.168.0.1`)和目的 IP 地址(`192.168.3.2`)(注意这里千万不要以为填写的是默认网关的 IP 地址,**从始至终这个数据包的两个 IP 地址都是不变的,只有 MAC 地址在不断变化**)封装在网络层头部,然后发送数据包 ![](https://cs-wiki.oss-cn-shanghai.aliyuncs.com/image-20230324124610593.png) 4)第一个交换机收到数据包后,发现目标 MAC 地址是 `MM-MM-MM-MM`,转发给第一个路由器 5)数据包来到了第一个路由器,发现其目标 IP 地址是 `192.168.3.2`,查看其路由表,发现了下一跳的地址是 `192.168.100.21` 6)所以此时该路由器需要做两件事,一是再次匹配路由表,找到下一跳 `192.168.100.21` 匹配的端口号,二是从这个端口把数据包转发出去 7)此时第二个路由器收到了数据包,看到其目的地址是 `192.168.3.2`,查询其路由表找到匹配的端口号,并准备从该端口把数据包转发出去 8)但此时路由器需要知道 `192.168.3.2` 的 MAC 地址才行,于是查看其 ARP 缓存,找到其 MAC 地址为 `FF-FF-FF-FF`,并将其封装在数据链路层头部,从上个步骤确定的端口将包转发出去。 9)如上图所示,对应的交换机收到了数据包,发现目的 MAC 地址为`FF-FF-FF-FF`,查询其 MAC 地址表,从对应的端口把数据包发出去。 10)数据包最终成功抵达计算机 F,F 发现目的 MAC 地址就是自己,于是收下了这个数据包 > 从各个节点的视角来看 > > **电脑视角**: > > - 首先我要知道我的 IP 以及对方的 IP > - 通过子网掩码判断我们是否在同一个子网 > - 在同一个子网就通过 ARP 获取对方 MAC 地址直接扔出去 > - 不在同一个子网就通过 ARP 获取默认网关的 MAC 地址直接扔出去 > > **交换机视角:** > > - 我收到的数据包必须有目标 MAC 地址 > - 通过 MAC 地址表查映射关系 > - 查到了就按照映射关系从我的指定端口发出去 > - 查不到就所有端口都发出去 > > **路由器视角:** > > - 我收到的数据包必须有目标 IP 地址 > - 通过路由表查映射关系 > - 查到了就按照映射关系从我的指定端口发出去(不在任何一个子网范围,走其路由器的默认网关也是查到了) > - 查不到则返回一个路由不可达的数据包