面试题:从输入网址到页面显示的全过程
01. 要看到一个网页,我们需要什么?
我们现在经常使用的网页其实是由三种语言书写而来的:HTML、Css 和 JavaScript,它们分别负责网页的结构、网页的样式和网页的交互功能;浏览器通过解析这些文件将内容展示给使用者,这些语言的支持让我们看到纷繁复杂的界面。
大家可能在本地书写过一些界面,通过浏览器来查看这些页面的效果,但我们在网络上访问到的网页大部分是不会存储在本地的,所以要通过网络请求去向有这些网页资源的主机请求这些文件,而这个主机就是常说的服务器(server),而发送请求的就是浏览器,浏览器作为客户端(client)。
这就回答了本章的问题,要完整的构建整个页面需要得到 HTML、CSS 和 JS 文件,以及一些静态资源比如图片视频等,这就是浏览器(client)要向服务器(server)请求的内容。
02. 去哪里找到这些资源呢?
这些资源是存储在 服务器 的目录中的,所以要得到这些资源首先要知道服务器的位置,其次是要知道这些资源在服务器的哪个目录中。
那什么承载着这些资源呢?
看看现在手上有什么?哦!只有一个网址,那就是它了,上面需要的信息就承载在这个长长的URL中了,现在来看看它是包含了什么信息:
http
:标识了访问数据使用的协议,HTTP 表示超文本传输协议,除此之外浏览器还可以使用 HTTPS 安全超文本传输协议Web 服务器
:即服务器(server)的地址,通常是以域名的方式表示。目录名及文件名
:资源在服务器的相对路径或者绝对路径,需要声明的是,这里的服务器指的是服务器 应用程序,而不是只运行服务器程序的主机,客户端请求的资源就包含在服务器应用程序中。
但当第一次进入网页的时候常常会发现请求网址后面没有目录名和文件名,这时候其实访问的就是服务器事先设置好的默认资源,比如常见的 index.html
主页。
DNS:从域名到 IP 地址
<1> 为什么需要 DNS
域名是互联网上用于标识和定位特定网络资源的 人类可读 的名称。
域名存在的意义是什么呢?来看这样两个内容:www.baidu.com
和 39.156.69.79
这两个哪个更容易记忆呢?毫无疑问会选择前者,比起复杂的数字,我们其实更擅长记忆有含义的文字。
域名是由人类可读的字符组成的,相比于 IP 地址,更容易被用户记忆和使用,其次其还具有商业标识价值和网络导航及搜索引擎优化的作用。
但网络中寻址仍然需要IP地址,这就需要一个专门保存域名和IP地址映射关系的服务器,这其实就是 DNS(Domain Name System);DNS 服务器的架构必然是分布式的,否则不可能承受住全世界的并发量,这也就导致一个 DNS 服务器不可能记录所有的映射情况。
<2> DNS 的解析流程
DNS 中的域名是通过 .
来分割的,越靠后的级别越高,比如 www.baidu.com
两个句号之间的部分代表一个域(zone),除去上面的部分还有一个根域,下一层 .com
代表顶级域,再往是 baidu.com
。每一个域都有根服务器的地址,因此当查询的时候只要找到任何一台 DNS 服务器就可以直接导航到根域服务器了。
根域服务器和顶级域服务器通常 不直接 提供域名解析的服务,而是负责提供它下层的服务器的信息。所以当导航到根域服务器的时候就可以顺藤摸瓜直到找到目标的下层服务器。
下面来展示一下域名解析的流程,比如说浏览器要查询一个 www.example.com
的服务器的 IP 地址:
- 客户端先去发送一个 DNS 请求向 本地DNS服务器 来请求解析这个域名,比如在家庭网络中,路由器就可以提供本地 DNS 的服务。
- 本地 DNS 服务器查找自己的缓存发现没有找到这个地址对应的 IP 地址,于是它向根域名服务器发送请求,根域名服务器不直接提供域名解析的服务,而是起到一个导航的作用,将
.com
的顶级域名服务器的地址返回给请求方。 - 请求方拿到这个 IP 地址后再去向顶级域名服务器请求解析,顶级域名服务器同样不直接提供域名解析的服务,它将
example.com
权威DNS服务器的地址交给了请求方。 - 这时候请求方再去请求
example.com
,权威域名服务器根据自己存储的权威数据将 IP 查询的结果返回给客户端。
那是不是每次请求都要来这么一次呢?
答案是否定的,因为本地DNS服务器通常会维护一个缓存,用于存储常用的 域名解析结果。
这样做的目的是为了提高域名解析的速度和效率,减少对上游DNS服务器的查询次数,从而加快网络访问的响应速度。
当完成域名解析之后,我们已经知道服务器的 IP 地址和资源目录,可以去请求资源了,但为了让服务器能够看懂我们的请求,需要做一些提前的规范,这就是 HTTP 协议。
03. HTTP:应该用什么样的格式请求?
HTTP(Hypertext Transfer Protocol,超文本传输协议)规范了客户端和服务器之间传输的数据格式和通信方式,它定义了一系列规则和约定,以确保在互联网上有效地传输和呈现 超文本数据。
- 方法: 请求的方法,常见的方法有 GET、POST、PUT、DELETE 等。
- 请求URI: 请求的统一资源标识符,指定了请求的资源。
- 协议版本: HTTP 协议的版本号,例如 HTTP/1.1。
- 请求头部字段: 请求头部字段和对应的值,用来传递请求的元数据信息,如 Host、User-Agent、Content-Type 等。
- 空行: 请求头部和请求体之间的空行。
- 请求正文: 请求的数据内容,仅在某些请求方法(如 POST)中存在。
响应报文的格式和请求报文类似
- 协议版本: HTTP 协议的版本号,例如 HTTP/1.1。
- 状态码: 响应的状态码,表示请求处理的结果,常见的状态码有 200(成功)、404(未找到)、500(服务器内部错误)等。
- 状态码描述: 状态码对应的描述信息。
- 响应头部字段: 响应头部字段和对应的值,用来传递响应的元数据信息,如 Content-Type、Content-Length、Cache-Control 等。
- 空行: 响应头部和响应体之间的空行。
- 响应正文: 响应的数据内容,通常包含请求的资源或者错误信息等。
HTTP 协议规定了请求报文和响应报文的格式,只有发送这样格式的数据才能让对等的协议体看懂发送的信息,但是这种复杂的结构不用我们去书写,因为浏览器会封装 HTTP 请求报文和解析 HTTP 响应报文,使得用户无需手动创建和解析 HTTP 报文。当用户在浏览器中输入网址或点击链接时,浏览器会自动发起 HTTP 请求,并处理 HTTP 响应,然后将响应的内容显示在用户界面上。
通过 HTTP 报文的规范,就可以来发送请求给服务器然后接收服务器返回的信息,但是本地有这么多进程,服务器上也有这么多进程,如何保证发出去的信息和返回的信息投到正确的信箱呢?
04. TCP:端口到端口的服务
<1> 基本介绍
为了解决进程到进程的问题,发送的信息要借助 TCP 的力量了,TCP 的报文中封装了源端口号和目的端口号,通过这两个字段就可以保证找到需要传递信息的应用。
因为需要 TCP 发送的内容可能很长,TCP 会将其分成一段一段的去发送,就需要一个 序号 来标识此时发送的是哪份内容;同样的,当对方收到报文后也要告诉发送方 我收到了哪个字段,这就是确认号。
TCP 没有请求和响应报文,所以需要一个标识位来标识这次的报文是什么内容,例如 SYN
是发起一个连接,ACK
是回复,RST
是重新连接,FIN
是结束连接等。
然后就是接收窗口,TCP 一次可以发送多个段,而对报文段的处理需要时间,没来得及处理完的时间会在缓冲队列中等待,但这个队列不是无限大的,因此接收方需要告诉发送方自己还剩下多少缓冲区,发送方每次发送的数据量不能超过这个缓冲区的大小,这就是常说的流量控制。
<2> 数据拆分
上面提到过当数据过大的时候呀对数据进行拆分,这主要是因为在网络中传递是数据长度是有限制的,比如在以太网中,数据帧的最大长度由最大传输单元来确定。在标准以太网中,MTU 的大小为 1500
字节。
而在除了 TCP 的头部,往下还会再添加 IP 的头部,到最终传输的时候大小一定不能超过这个 MTU,而 MTU 减去 TCP 和 IP 头部剩余的大小称为 MSS,当应用层传递下来的数据超过了这个大小的时候就必须对其进行切割了。
现在确定了双方主机可以找到对应的投递信箱了,接下来就是在茫茫的网络中寻找对方主机在哪。
<3> 三次握手
在发送数据之前,TCP 会进行三次握手,来建立两个主机之间的链接状态
- 客户端发送连接请求:客户端首先向服务器发送一个 SYN(同步)报文段,其中设置了一个初始序列号(ISN)用于标识数据流的起始位置,并指明客户端希望建立连接的端口号。
- 服务器确认连接请求:服务器收到客户端的 SYN 报文段后,会回复一个 SYN+ACK 报文段,其中 SYN 标志位表示同步,ACK 标志位表示确认。服务器也会为自己生成一个 ISN,并将其发送给客户端,同时确认客户端的序列号。
- 客户端确认连接请求:客户端收到服务器的 SYN+ACK 报文段后,会发送一个 ACK 报文段作为确认。此时,TCP 连接已经建立起来,通信双方可以开始进行数据传输。
05. IP:主机到主机的服务
<1> 基本理解
在 IP 的报文中有 源地址和目标地址的 信息,这个信息就是上面通过 DNS 解析得到的 IP 地址,它从应用层传递下来,最终被包含在 IP 的报文中。
<2> 路由表
根据这些信息就相当于有了目的地,但选择哪条路径则需要通过查询 路由表 来得出,下面来看一个简单的路由表案例:
目标网络 | 子网掩码 | 下一跳网关 | 接口 |
---|---|---|---|
192.168.1.0 | 255.255.255.0 | - | eth0 |
192.168.2.0 | 255.255.255.0 | 192.168.1.1 | eth1 |
10.0.0.0 | 255.0.0.0 | 192.168.1.2 | eth2 |
0.0.0.0 | 0.0.0.0 | 192.168.1.254 | eth3 |
- 目标网络:指定了数据包要到达的目标网络的 IP 地址。
- 子网掩码:确定了目标网络的范围,以便匹配目标网络。通过和目标网络进行逻辑与操作,可以提取出目标网络的网络号。
- 下一跳网关:当数据包要发送到目标网络时,指定了数据包应该经过的下一跳路由器的 IP 地址。如果下一跳网关为 “-”,表示目标网络就在本地网络中,不需要经过路由器。
- 接口:指定了数据包应该从哪个网络接口发送出去。当下一跳网关为 “-” 时,接口通常会直接指定为本地网络接口。
<3> 补充:子网掩码的案例
假设有一个 IP 地址为 192.168.1.100
,子网掩码为 255.255.255.0
的网络。
- 首先,让将这两个地址转换为二进制形式:
- IP 地址:
11000000.10101000.00000001.01100100
- 子网掩码:
11111111.11111111.11111111.00000000
- IP 地址:
- 染红可以根据子网掩码来确定这个 IP 地址所在的网络号和主机号,在子网掩码中,每个 1 位代表网络位,每个 0 位代表主机位。
- 网络位:
11000000.10101000.00000001
- 主机位:
01100100
- 网络位:
- 所以,这个 IP 地址
192.168.1.100
属于192.168.1.0
这个网络。- 在这个网络中,主机号范围是从
00000000
到11111111
,即从 0 到 255。因此,这个网络可以容纳从192.168.1.1
到192.168.1.254
的主机。
- 在这个网络中,主机号范围是从
继续前面的内容,源主机使用自己的 IP 地址和子网掩码进行逻辑与操作,计算出主机所在网络的网络号,如果目标主机的 IP 地址与计算出的网络号在同一个网络中,那么它们就可以直接通信。否则,源主机将向路由器发送数据,通过路由器转发数据到目标主机所在的网络,体现在路由表中就是没有查询到对应的 IP 地址,于是通过默认网关将发送请求交给路由器了。
通过不断 查询路由表 和 转发数据包,最终可以将数据包送达目标主机所在的子网,这时候离着目标的主机已经非常接近了,但是这时候突然发现到了子网中,IP 地址好像不太好用了,因为在局域网中主机之间通信通常是通过 MAC 地址进行的。
在局域网中,主机之间可以直接通信,不需要经过路由器。而 MAC 地址是用于在同一个局域网中唯一标识每台设备的地址,因此主机之间的直接通信适合使用 MAC 地址。
06. 路由器:出口和入口
当一台计算机向外网传递数据时,数据包通常会首先到达目标主机所在的子网中的路由器。
路由器也是依靠路由表进行转发的操作,通过路由器可以实现不同网络之间的连接和通信。路由器是连接不同网络的设备,它具有路由功能,可以根据目标 IP 地址将数据包从一个网络转发到另一个网络。
源主机发送的信息先会到达子网的路由器,通过路径上的路由器不断的查表和数据转发最终到达了目标主机子网的路由器,其路由表的使用方式和上面讲到的基本一致。
07. MAC:局域网内主机和主机的通信
MAC地址也叫物理地址、硬件地址,由网络设备制造商生产时烧录在网卡(Network lnterface Card)的EPROM(一种闪存芯片,通常可以通过程序擦写)。IP地址与MAC地址在计算机里都是以二进制表示的,IP地址是32位的,而MAC地址则是48位的。
MAC地址的长度为48位(6个字节),通常表示为12个16进制数,如:00-16-EA-AE-3C-40就是一个MAC地址,其中前3个字节,16进制数00-16-EA代表网络硬件制造商的编号,它由IEEE(电气与电子工程师协会)分配,而后3个字节,16进制数AE-3C-40代表该制造商所制造的某个网络产品(如网卡)的系列号。只要不更改自己的MAC地址,MAC地址在世界是唯一的。形象地说,MAC地址就如同身份证上的身份证号码,具有唯一性。
数据经过长途跋涉终于到达了目标主机的子网,它看着手里的 IP 地址和通信需要的 MAC 地址陷入了沉思,但是还好有路由器,当主机知道目标主机的 IP 地址但不知道其 MAC 地址时,它会在局域网中广播一个 ARP 请求,请求对应 IP 地址的主机回应其 MAC 地址。
但是每次都要广播去请求 MAC 地址非常麻烦,所以和 DNS 解析一样,每个主机也会维护一个 MAC 地址的缓存,用来直接将 IP 映射成 MAC 地址。
08. 网卡:数字信号到电信号
最终交到传输者手中的是一大堆 二进制 数,但二进制数是无法直接在链路中进行传递的,所以需要将数字信号转到电信号,这就网卡的工作。
在数据传输过程中,网卡负责封装数据成为数据帧(Frame),并添加必要的控制信息(如 MAC 地址、帧起始符、帧结束符等),以确保数据能够在网络上正确传输。
网卡负责将计算机中的数据转换为网络可识别的格式,并在计算机和网络设备之间进行数据传输
09. 交换机:数据帧的转发
在以太网中,数据传输通常会经过交换机。交换机是用于连接多台计算机和其他网络设备的网络设备,它负责在局域网中转发数据帧,并根据目标 MAC 地址将数据帧传送到目标设备。当一台计算机想要向另一台计算机发送数据时,它会将数据封装成数据帧,然后通过网络接口发送到交换机。交换机会根据数据帧中的目标 MAC 地址,将数据帧转发到与目标设备相连的端口,从而实现数据传输。
交换机能够根据数据帧中的目标 MAC 地址,将数据包准确地转发到目标主机所在的端口,从而实现局域网内部的通信。
交换机中有一个 MAC 地址表,这个表中有 MAC 地址和发送端口的信息,通过将表中的信息与数据帧中的 MAC 地址的信息做对比可以找到指定的发送端口,接着将这个信息发送到与目标设备相连的端口,完成通信。
如果地址表中找不到对应的 MAC 地址。在这种情况下,交换机无法判断应该把包转发到哪个端口,会将包转发到除了源端口之外的所有端口上,无论该设备连接在哪个端口上都能收到这个包。如果不需要这个包的主机检查 MAC 地址发现不匹配之后就会直接丢弃,这样能保证发送到需要的主机上。
10. 接收数据
通过交换机的传递,现在数据终于到达了目标主机,目标主机需要的是里面传输的数据,所以它会将传递来的头部一点点去掉,最终只剩下数据块,将这个数据块交给制定的端口,这样终于算是完成了一次网络通信。
因为我这里从路由器开始是按照接收方的顺序讲述的,是 路由器 => 交换机 => 目标主机 的顺序,如果是发送方就是 源主机 => 交换机 => 目标主机,其余大致都是相同的,注意一下顺序问题即可。
参考文章:
- 键入网址到网页显示,期间发生了什么?博主:
- 小林coding
- HTTP报文格式详解
- 博主:shirley_zx