灵魂拷问!浏览器输入「xxxxhub」的背后..... (3)

ARP 协议的全称是 Address Resolution Protocol(地址解析协议),它是一个通过用于实现从 IP 地址到 MAC 地址的映射,即询问目标 IP 对应的 MAC 地址 的一种协议。

简而言之,ARP 就是一种解决地址问题的协议,它以 IP 地址为线索,定位下一个应该接收数据分包的主机 MAC 地址。如果目标主机不在同一个链路上,那么会查找下一跳路由器的 MAC 地址。

关于为什么有了 IP 地址,还要有 MAC 地址概述可以参看知乎这个回答 https://www.zhihu.com/question/21546408

ARP 的大致工作流程如下

假设 A 和 B 位于同一链路,不需要经过路由器的转换,主机 A 向主机 B 发送一个 IP 分组,主机 A 的地址是 192.168.1.2 ,主机 B 的地址是 192.168.1.3,它们都不知道对方的 MAC 地址是啥,主机 C 和 主机 D 是同一链路的其他主机。

灵魂拷问!浏览器输入「xxxxhub」的背后.....

主机 A 想要获取主机 B 的 MAC 地址,通过主机 A 会通过广播 的方式向以太网上的所有主机发送一个 ARP 请求包,这个 ARP 请求包中包含了主机 A 想要知道的主机 B 的 IP 地址的 MAC 地址。

灵魂拷问!浏览器输入「xxxxhub」的背后.....

主机 A 发送的 ARP 请求包会被同一链路上的所有主机/路由器接收并进行解析。每个主机/路由器都会检查 ARP 请求包中的信息,如果 ARP 请求包中的目标 IP 地址 和自己的相同,就会将自己主机的 MAC 地址写入响应包返回主机 A

灵魂拷问!浏览器输入「xxxxhub」的背后.....

由此,可以通过 ARP 从 IP 地址获取 MAC 地址,实现同一链路内的通信。

所以,要想发送 ARP 广播,我们需要有一个目标 IP 地址,同时还需要知道用于发送 ARP 广播的接口的 MAC 地址。

这里会涉及到 ARP 缓存的概念。

现在你知道了发送一次 IP 分组前通过发送一次 ARP 请求就能够确定 MAC 地址。那么是不是每发送一次都得经过广播 -> 封装 ARP 响应 -> 返回给主机这一系列流程呢?

想想看,浏览器是如何做的?浏览器内置了缓存能够缓存你最近经常使用的地址,那么 ARP 也是一样的。ARP 高效运行的关键就是维护每个主机和路由器上的 ARP 缓存(或表)。这个缓存维护着每个 IP 到 MAC 地址的映射关系。通过把第一次 ARP 获取到的 MAC 地址作为 IP 对 MAC 的映射关系到一个 ARP 缓存表中,下一次再向这个地址发送数据报时就不再需要重新发送 ARP 请求了,而是直接使用这个缓存表中的 MAC 地址进行数据报的发送。每发送一次 ARP 请求,缓存表中对应的映射关系都会被清除。

通过 ARP 缓存,降低了网络流量的使用,在一定程度上防止了 ARP 的大量广播。

灵魂拷问!浏览器输入「xxxxhub」的背后.....

一般来说,发送过一次 ARP 请求后,再次发送相同请求的几率比较大,因此使用 ARP 缓存能够减少 ARP 包的发送,除此之外,不仅仅 ARP 请求的发送方能够缓存 ARP 接收方的 MAC 地址,接收方也能够缓存 ARP 请求方的 IP 和 MAC 地址,如下所示

灵魂拷问!浏览器输入「xxxxhub」的背后.....

不过,MAC 地址的缓存有一定期限,超过这个期限后,缓存的内容会被清除

深入理解 ARP 协议的话,可以参考 cxuan 的这篇文章。

所以,浏览器会首先查询 ARP 缓存,如果缓存命中,我们返回结果:目标 IP = MAC。

如果缓存没有命中:

查看路由表,看看目标 IP 地址是不是在本地路由表中的某个子网内。是的话,使用跟那个子网相连的接口,否则使用与默认网关相连的接口。

查询选择的网络接口的 MAC 地址

我们发送一个数据链路层的 ARP 请求:

根据连接主机和路由器的硬件类型不同,可以分为以下几种情况:

直连:

如果我们和路由器是直接连接的,路由器会返回一个 ARP Reply (见下面)。

集线器:

如果我们连接到一个集线器,集线器会把 ARP 请求向所有其它端口广播,如果路由器也连接在其中,它会返回一个 ARP Reply 。

交换机:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsxwwz.html