假如 A 给 B 发送数据,由于它们直接连着交换机,所以 A 直接发出如下数据包即可,其实网络层没有体现出作用。
但假如 A 给 C 发送数据,A 就需要先转交给路由器,然后再由路由器转交给 C。由于最底层的传输仍然需要依赖以太网,所以数据包是分成两段的。
A ~ 路由器这段的包如下:
路由器到 C 这段的包如下:
好了,上面说的两种情况(A->B,A->C),相信细心的读者应该会有不少疑问,下面我们一个个来展开。
A 给 C 发数据包,怎么知道是否要通过路由器转发呢?
答案:子网
如果源 IP 与目的 IP 处于一个子网,直接将包通过交换机发出去。
如果源 IP 与目的 IP 不处于一个子网,就交给路由器去处理。
好,那现在只需要解决,什么叫处于一个子网就好了。
192.168.0.1 和 192.168.0.2 处于同一个子网
192.168.0.1 和 192.168.1.1 处于不同子网
这两个是我们人为规定的,即我们想表示,对于 192.168.0.1 来说:
192.168.0.xxx 开头的,就算是在一个子网,否则就是在不同的子网。
那对于计算机来说,怎么表达这个意思呢?于是人们发明了子网掩码的概念
假如某台机器的子网掩码定为 255.255.255.0
这表示,将源 IP 与目的 IP 分别同这个子网掩码进行与运算,相等则是在一个子网,不相等就是在不同子网,就这么简单。
比如
A电脑:192.168.0.1 & 255.255.255.0 = 192.168.0.0
B电脑:192.168.0.2 & 255.255.255.0 = 192.168.0.0
C电脑:192.168.1.1 & 255.255.255.0 = 192.168.1.0
D电脑:192.168.1.2 & 255.255.255.0 = 192.168.1.0
那么 A 与 B 在同一个子网,C 与 D 在同一个子网,但是 A 与 C 就不在同一个子网,与 D 也不在同一个子网,以此类推。
所以如果 A 给 C 发消息,A 和 C 的 IP 地址分别 & A 机器配置的子网掩码,发现不相等,则 A 认为 C 和自己不在同一个子网,于是把包发给路由器,就不管了,之后怎么转发,A 不关心。
A 如何知道,哪个设备是路由器?
答案:在 A 上要设置默认网关
上一步 A 通过是否与 C 在同一个子网内,判断出自己应该把包发给路由器,那路由器的 IP 是多少呢?
其实说发给路由器不准确,应该说 A 会把包发给默认网关。
对 A 来说,A 只能直接把包发给同处于一个子网下的某个 IP 上,所以发给路由器还是发给某个电脑,对 A 来说也不关心,只要这个设备有个 IP 地址就行。
所以默认网关,就是 A 在自己电脑里配置的一个 IP 地址,以便在发给不同子网的机器时,发给这个 IP 地址。
仅此而已!
路由器如何知道C在哪里?
答案:路由表
现在 A 要给 C 发数据包,已经可以成功发到路由器这里了,最后一个问题就是,路由器怎么知道,收到的这个数据包,该从自己的哪个端口出去,才能直接(或间接)地最终到达目的地 C 呢。
路由器收到的数据包有目的 IP 也就是 C 的 IP 地址,需要转化成从自己的哪个端口出去,很容易想到,应该有个表,就像 MAC 地址表一样。
这个表就叫路由表。
至于这个路由表是怎么出来的,有很多路由算法,本文不展开,因为我也不会哈哈~
不同于 MAC 地址表的是,路由表并不是一对一这种明确关系,我们下面看一个路由表的结构。
| 目的地址 | 子网掩码 | 下一跳 | 端口 |
|---|---|---|---|
| 192.168.0.0 | 255.255.255.0 | 0 | |
| 192.168.0.254 | 255.255.255.255 | 0 | |
| 192.168.1.0 | 255.255.255.0 | 1 | |
| 192.168.1.254 | 255.255.255.255 | 1 |
我们学习一种新的表示方法,由于子网掩码其实就表示前多少位表示子网的网段,所以如 192.168.0.0(255.255.255.0) 也可以简写为 192.168.0.0/24
| 目的地址 | 下一跳 | 端口 |
|---|---|---|
| 192.168.0.0/24 | 0 | |
| 192.168.0.254/32 | 0 | |
| 192.168.1.0/24 | 1 | |
| 192.168.1.254/32 | 1 |
这就很好理解了,路由表就表示,192.168.0.xxx 这个子网下的,都转发到 0 号端口,192.168.1.xxx 这个子网下的,都转发到 1 号端口。下一跳列还没有值,我们先不管
配合着结构图来看(这里把子网掩码和默认网关都补齐了)
刚才说的都是 IP 层,但发送数据包的数据链路层需要知道 MAC 地址,可是我只知道 IP 地址该怎么办呢?
答案:arp
假如你(A)此时不知道你同伴 B 的 MAC 地址(现实中就是不知道的,刚刚我们只是假设已知),你只知道它的 IP 地址,你该怎么把数据包准确传给 B 呢?
答案很简单,在网络层,我需要把 IP 地址对应的 MAC 地址找到,也就是通过某种方式,找到192.168.0.2对应的 MAC 地址BBBB。
这种方式就是arp 协议,同时电脑 A 和 B 里面也会有一张arp 缓存表,表中记录着IP 与 MAC 地址的对应关系。
| IP 地址 | MAC 地址 |
|---|---|
| 192.168.0.2 | BBBB |
一开始的时候这个表是空的,电脑 A 为了知道电脑 B(192.168.0.2)的 MAC 地址,将会广播一条 arp 请求,B 收到请求后,带上自己的 MAC 地址给 A 一个响应。此时 A 便更新了自己的 arp 表。
这样通过大家不断广播 arp 请求,最终所有电脑里面都将 arp 缓存表更新完整。
总结一下
好了,总结一下,到目前为止就几条规则
从各个节点的视角来看
电脑视角:
首先我要知道我的 IP 以及对方的 IP
通过子网掩码判断我们是否在同一个子网
在同一个子网就通过 arp 获取对方 mac 地址直接扔出去
不在同一个子网就通过 arp 获取默认网关的 mac 地址直接扔出去
交换机视角:
我收到的数据包必须有目标 MAC 地址
通过 MAC 地址表查映射关系
查到了就按照映射关系从我的指定端口发出去
查不到就所有端口都发出去
路由器视角:
我收到的数据包必须有目标 IP 地址
通过路由表查映射关系
查到了就按照映射关系从我的指定端口发出去(不在任何一个子网范围,走其路由器的默认网关也是查到了)
查不到则返回一个路由不可达的数据包
如果你嗅觉足够敏锐,你应该可以感受到下面这句话:
网络层(IP协议)本身没有传输包的功能,包的实际传输是委托给数据链路层(以太网中的交换机)来实现的。
涉及到的三张表分别是
交换机中有MAC 地址表用于映射 MAC 地址和它的端口
路由器中有路由表用于映射 IP 地址(段)和它的端口
电脑和路由器中都有arp 缓存表用于缓存 IP 和 MAC 地址的映射关系
这三张表是怎么来的
MAC 地址表是通过以太网内各节点之间不断通过交换机通信,不断完善起来的。
路由表是各种路由算法 + 人工配置逐步完善起来的。
arp 缓存表是不断通过 arp 协议的请求逐步完善起来的。
知道了以上这些,目前网络上两个节点是如何发送数据包的这个过程,就完全可以解释通了!
那接下来我们就放上本章最后一个网络拓扑图吧,请做好战斗准备!
这时路由器 1 连接了路由器 2,所以其路由表有了下一条地址这一个概念,所以它的路由表就变成了这个样子。如果匹配到了有下一跳地址的一项,则需要再次匹配,找到其端口,并找到下一跳 IP 的 MAC 地址。
也就是说找来找去,最终必须能映射到一个端口号,然后从这个端口号把数据包发出去。
| 目的地址 | 下一跳 | 端口 |
|---|---|---|
| 192.168.0.0/24 | 0 | |
| 192.168.0.254/32 | 0 | |
| 192.168.1.0/24 | 1 | |
| 192.168.1.254/32 | 1 | |
| 192.168.2.0/24 | 192.168.100.5 | |
| 192.168.100.0/24 | 2 | |
| 192.168.100.4/32 | 2 |