maps.google.com_maps.google.com_maps.google.com

本文将以 Web 页面的请求历程为例,来和你聊聊计算机网络中这些协议是怎样工作的、数据包是怎么收发的,从输入 URL 、敲击回车到最终完成页面呈现在你面前的这个过程。

首先,我打开了 Web Browser ,然后在 Google 浏览器 URL 地址栏中输入了maps.google.com。

然后 ……

查找 DNS 缓存

浏览器在这个阶段会检查四个地方是否存在缓存,第一个地方是浏览器缓存,这个缓存就是 DNS 记录。

浏览器会为你访问过的网站在固定期限内维护 DNS 记录。因此,它是第一个运行 DNS 查询的地方。浏览器首先会检查这个网址在浏览器中是否有一条对应的 DNS 记录,用来找到目标网址的 IP 地址。

我是 chrome 浏览器,所以在 mac 中,无法使用chrome://net-internals/#dns找到对应的 IP 地址,在 windows 中是可以找到的。

那么 mac 怎么查询 DNS 记录呢?你可以使用nslookup命令来查找,但这不是我们讨论的重点。

DNS(Domain Name System)是一个分布式的数据库,它用于维护网址 URL 到其 IP 地址的映射关系。在互联网中,IP 地址是计算机所能够理解的一种地址,而 DNS 的这种别名地址是我们人类能够理解和记忆的地址,DNS 就负责把人类记忆的地址映射成计算机能够理解的地址,每个 URL 都有唯一的 IP 地址进行对应。

举个例子,google 的官网是 ,而 google 的 ip 地址是 216.58.200.228 ,这两个地址你在 URL 上输入哪个都能访问,但是 IP 地址不好记忆,而 google.com 简单明了。DNS 就相当于是我们几年前使用的家庭电话薄,比如你想给 cxuan 打电话,你有可能记不住 cxuan 的电话号码,此时你需要查询电话薄来找到 cxuan 的电话号码。

浏览器第二个需要检查的地方就是操作系统缓存。如果 DNS 记录不在浏览器缓存中,那么浏览器将对操作系统发起系统调用,Windows 下就是getHostName。

在 Linux 和大部分 UNIX 系统上,除非安装了nscd,否则操作系统可能没有 DNS 缓存。

nscd 是 Linux 系统上的一种名称服务缓存程序。

浏览器第三个需要检查的地方是路由器缓存,如果 DNS 记录不在自己电脑上的话,浏览器就会和与之相连的路由器共同维护 DNS 记录。

如果与之相连的路由器也没有 DNS 记录的话,浏览器就会检查ISP中是否有缓存。ISP 缓存就是你本地通信服务商的缓存,因为 ISP 维护着自己的 DNS 服务器,它缓存 DNS 记录的本质也是为了降低请求时间,达到快速响应的效果。一旦你访问过某些网站,你的 ISP 可能就会缓存这些页面,以便下次快速访问。对于经常看小电影的你是否感到震惊呢?如果家里还安装了一个可以联网的摄像头的话,那就有点嗨皮了。

你肯定比较困惑为什么第一步浏览器需要检查这么多缓存,你可能会感到不舒服,因为缓存可能会透露我们的隐私,但是这些缓存在调节网络流量和缩短数据传输时间等方面至关重要。

所以,上面涉及到 DNS 缓存的查询过程如下。

maps.google.com_maps.google.com_maps.google.com

如果上面四个步骤中都不存在 DNS 记录,那么就表示不存在 DNS 缓存,这个时候就需要发起 DNS 查询,以查找目标网址(本示例中是 maps.google.com)的 IP 地址。

发起 DNS 查询

如上所述,如果想要使我的计算机和 maps.google.com 建立连接并进行通信的话,我需要知道 maps.google.com 的 IP 地址,由于 DNS 的设计原因,本地 DNS 可能无法给我提供正确的 IP 地址,那么它就需要在互联网上搜索多个 DNS 服务器,来找到网站的正确 IP 地址。

这里有个疑问,为什么我需要搜索多个 DNS 服务器的来找到网站的 IP 地址呢?一台服务器不行吗?

因为 DNS 是分布式域名服务器,每台服务器只维护一部分 IP 地址到网络地址的映射,没有任何一台服务器能够维持全部的映射关系。

在 DNS 的早期设计中只有一台 DNS 服务器。这台服务器会包含所有的 DNS 映射。这是一种集中式的设计,这种设计并不适用于当今的互联网,因为互联网有着数量巨大并且持续增长的主机,这种集中式的设计会存在以下几个问题

所以在当今网络情况下 DNS 不可能集中式设计,因为它完全没有可扩展能力,所以采用分布式设计,这种设计的特点如下

分布式、层次数据库。

首先分布式设计首先解决的问题就是 DNS 服务器的扩展性问题,因此 DNS 使用了大量的 DNS 服务器,它们的组织模式一般是层次方式,并且分布在全世界范围内。没有一台 DNS 服务器能够拥有因特网上所有主机的映射。相反,这些映射分布在所有的 DNS 服务器上。

大致来说有三种 DNS 服务器:根 DNS 服务器、顶级域(Top-Level Domain, TLD) DNS 服务器和权威 DNS 服务器。这些服务器的层次模型如下图所示

在了解了 DNS 服务器的设计理念之后,我们回到 DNS 查找的步骤上来,DNS 的查询方式主要分为三种

DNS 查找中会出现三种类型的查询。通过组合使用这些查询,优化的 DNS 解析过程可缩短传输距离。在理想情况下,可以使用缓存的记录数据,从而使 DNS 域名服务器能够直接使用非递归查询。

maps.google.com_maps.google.com_maps.google.com

maps.google.com_maps.google.com_maps.google.com

上面负责开始 DNS 查找的介质就是DNS 解析器,它一般是 ISP 维护的 DNS 服务器,它的主要职责就是通过向网络中其他 DNS 服务器询问正确的 IP 地址。

所以对于 maps.google.com 这个域名来说,如果 ISP 维护的服务器没有 DNS 缓存记录,它就会向 DNS 根服务器地址发起查询,根名称服务器会将其重定向到 .com 顶级域名服务器。.com 顶级域名服务器会将其重定向到google.com 权威服务器。google.com 名称服务器将在其 DNS 记录中找到 maps.google.com 匹配的 IP 地址,并将其返回给您的 DNS 解析器,然后将其发送回你的浏览器。

这里值得注意的是,DNS 查询报文会经过许多路由器和设备才会达到根域名等服务器,每经过一个设备或者路由器都会使用路由表来确定哪种路径是数据包达到目的地最快的选择。这里面涉及到路由选择算法,如果小伙伴们想要了解路由选择算法,可以看看这篇文章 #anc3

ARP 请求

我看了很多篇文章都没有提到这一点,那就是 ARP 请求的这个过程。

什么时候需要发送 ARP 请求呢?

这里其实有个前提条件

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

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

关于为什么有了 IP 地址,还要有 MAC 地址概述可以参看知乎这个回答

ARP 的大致工作流程如下

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

maps.google.com_maps.google.com_maps.google.com

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

maps.google.com_maps.google.com_maps.google.com

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

maps.google.com_maps.google.com_maps.google.com

由此,可以通过 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 的大量广播。

maps.google.com_maps.google.com_maps.google.com

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

maps.google.com_maps.google.com_maps.google.com

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

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

如果缓存没有命中:

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

直连:

集线器:

交换机:

ARP Reply:

现在我们有了 DNS 服务器或者默认网关的 IP 地址,我们可以继续 DNS 请求了:

(上述均来自:#dns)

封装 TCP 数据包

浏览器得到目标服务器的 IP 地址后,根据 URL 中的端口可以知道端口号 (http 协议默认端口号是 80, https 默认端口号是 443),会准备 TCP 数据包。数据包的封装会经过下面的层层处理,数据到达目标主机后,目标主机会解析数据包,完整的请求和解析过程如下。

maps.google.com_maps.google.com_maps.google.com

浏览器与目标服务器建立 TCP 连接

在经过上述 DNS 和 ARP 查找流程后,浏览器就会收到一个目标服务器的 IP 和 MAC地址,然后浏览器将会和目标服务器建立连接来传输信息。这里可以使用很多种 Internet 协议,但是 HTTP 协议建立连接所使用的运输层协议是 TCP 协议。所以这一步骤是浏览器与目标服务器建立 TCP 连接的过程。

TCP 的连接建立需要经过 TCP/IP 的三次握手,三次握手的过程其实就是浏览器和服务器交换 SYN 同步和 ACK 确认消息的过程。

假设图中左端是客户端主机,右端是服务端主机,一开始,两端都处于CLOSED(关闭)状态。

maps.google.com_maps.google.com_maps.google.com

服务端进程准备好接收来自外部的 TCP 连接。然后服务端进程处于LISTEN状态,等待客户端连接请求。

客户端向服务器发出连接请求,请求中首部同步位 SYN = 1,同时选择一个初始序号 sequence ,简写 seq = x。SYN 报文段不允许携带数据,只消耗一个序号。此时,客户端进入SYN-SEND状态。

服务器收到客户端连接后,,需要确认客户端的报文段。在确认报文段中,把 SYN 和 ACK 位都置为 1 。确认号是 ack = x + 1,同时也为自己选择一个初始序号 seq = y。请注意,这个报文段也不能携带数据,但同样要消耗掉一个序号。此时,TCP 服务器进入SYN-RECEIVED(同步收到)状态。

客户端在收到服务器发出的响应后,还需要给出确认连接。确认连接中的 ACK 置为 1 ,序号为 seq = x + 1,确认号为 ack = y + 1。TCP 规定,这个报文段可以携带数据也可以不携带数据,如果不携带数据,那么下一个数据报文段的序号仍是 seq = x + 1。这时,客户端进入ESTABLISHED (已连接)状态

服务器收到客户的确认后,也进入ESTABLISHED状态。

这样三次握手建立连接的阶段就完成了,双方可以直接通信了。

限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: lzxmw777

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注