计网基础——从输入URL到看到页面发生了什么?

loading 2022年04月12日 133次浏览

1.概览

简单概括,共有以下过程:

  1. 先对URL解析,然后进行DNS解析
  2. 建立TCP连接
  3. 客户端发送HTTP请求至服务器
  4. 服务器处理请求并返回HTTP报文至客户端
  5. 浏览器解析渲染页面
  6. 断开TCP连接

2. 先对URL解析,然后进行DNS解析

浏览器第一步工作是对URL进行解析,根据相关的信息生成HTTP请求信息

客户端只要能够找到任意一台 DNS 服务器,就可以通过它找到根域 DNS 服务器,然后再一路顺藤摸瓜找到位于下层的某台目标 DNS 服务器。

DNS:域名系统。作为域名IP地址互相映射的一个分布式数据库。使用UDP协议传输,因为机制简单,开销小,性能更好

一旦发起请求,浏览器首先就是要去解析这个域名为对应的IP地址,因为浏览器不能直接通过域名找到服务器,而是要通过IP地址:

  1. 首先查看浏览器缓存,再看操作系统缓存,再看本地hosts文件,若缓存中存了地址则直接返回,若都没有存才进行下一步。

  2. 根据客户端的TCP/IP设置中填写的DNS服务器地址发送DNS请求到本地DNS服务器

  3. 服务器首先查询自己的缓存记录,如果有,则直接返回,此过程为递归的查询方式;否则本地DNS服务器向DNS根服务器进行查询。

  4. 根服务器没有记录具体的映射关系,而是告诉本地服务器可以去对应的域服务器上查询,并提供地址,此过程为迭代的查询方式

DNS两种查询方式:递归查询和迭代查询
1.递归查询:局部DNS服务器自己负责向其他DNS服务器进行查询,一般是先向该域名的根域服务器查询,再由根域名服务器一级级向下查询。最后得到的查询结果返回给局部DNS服务器,再由局部DNS服务器返回给客户端。
2.迭代查询:只是帮你找到相关的服务器而已,而不会帮你去查。比如说:根 DNS 收到来自本地 DNS 的请求后,发现后置是 .com,说:“www.server.com 这个域名归 .com 区域管理”,我给你 .com 顶级域名服务器地址给你,你去问问它吧。

5.域服务器仍然不会直接返回映射关系,而是告诉本地服务器其域名的解析服务器的地址

6.最后,本地服务器向域名的解析服务器(权威DNS服务器)发出请求,就成功收到一个映射关系,并将这个映射关系保存在缓存中。然后本地服务器再将映射出的IP地址返回给客户端,准备建立连接。

也就是说,本地DNS服务器向根/顶级域名/权威DNS服务器查询的过程就是递归查询(自己查不到,去委托别人查,并不断重复)。而根/顶级域名/权威DNS服务器的查询方法就是迭代查询。(接收到本地DNS服务器的请求后,自己查不到,返回一个引用)

3. 建立TCP连接

TCP通过三次握手建立连接
具体关于三次握手四次挥手见另一篇博客

4. 客户端发送HTTP请求至服务器

4.1 请求报文结构

TCP三次握手结束之后,开始发送HTTP请求报文:

(1) 首先要看协议是不是https,如果是的话,则要首先进行加密。关于https具体内容见另一篇博客

(2) 浏览器向服务器的ip地址发送请求获取页面,http请求报文由三部分组成:请求行,请求头和请求正文

请求行包括请求方法,URL和协议版本

  • 请求方法:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE
  • URL:请求地址
  • 协议版本:HTTP版本号
POST /chapter17/user.html HTTP/1.1

请求头包含请求的附加信息,由键值对组成,每行一对
请求头通知服务器有关于客户端请求的信息。它包含许多有关的客户端环境和请求正文的有用信息。
其中比如:Host,表示主机名;Connection,HTTP/1.1 增加的,使用 keepalive,即持久连接,一个连接可以发多个请求;User-Agent,请求发出者。

请求包体可以承载多个请求参数的数据,包含回车符、换行符和请求数据,并不是所有请求都具有请求数据

name=tom&password=1234&realName=tomson

上面代码,承载着 name、password、realName 三个请求参数。

4.2 具体传输过程

发送请求过程中,大致会经历这么一个顺序:TCP->IP->MAC->网卡->交换机->路由器->服务器

4.2.1 传输层 TCP

TCP实现可靠传输,具体的TCP内容见别的博客。

如果HTTP请求消息比较长,超过了MSS的长度,这时 TCP 就需要把 HTTP 的数据拆解成一块块的数据发送,而不是一次性发送所有数据。

MTU:一个网络包的最大长度,以太网中一般为 1500 字节。
MSS:除去 IP 和 TCP 头部之后,一个网络包所能容纳的 TCP 数据的最大长度。

数据会被以 MSS 的长度为单位进行拆分,拆分出来的每一块数据都会被放进单独的网络包中。也就是在每个被拆分的数据加上 TCP 头信息,然后交给 IP 模块来发送数据

随后给HTTP报文添加上TCP头部,组装好后将报文交给接下来的网络层处理。

4.2.2 网络层 IP

来到网络层,TCP 模块在执行连接、收发、断开等各阶段操作时,都需要委托 IP 模块将数据封装成网络包发送给通信对象。

由于内容过多,具体IP内容见别的博客,此处只说一些传输要点。

假设客户端有多个网卡,就会有多个 IP 地址,那 IP 头部的源地址应该选择哪个 IP 呢?

根据路由表来判断哪一个网卡作为源地址IP,将目标地址和子网掩码进行与运算,检查得出的结果是否和Destination相匹配。若都不匹配取0.0.0.0默认网关。

4.2.3 网络接口层 MAC

加上了TCP和IP头部后来到这层,还要在前面加上MAC头部。

MAC 头部是以太网使用的头部,它包含了接收方和发送方的 MAC 地址等信息。

如何获取接收方MAC地址?

通过ARP协议来实现:
如果ARP缓存中存了对方的MAC地址,就直接使用即可。

否则ARP 协议会在以太网中以广播的形式,对以太网所有的设备喊出:“这个 IP 地址是谁的?请把你的 MAC 地址告诉我”。

然后就会有人回答:“这个 IP 地址是我的,我的 MAC 地址是 XXXX”。

这样就得到了对方的MAC地址,得到后写入MAC头部即可。

4.2.4 物理层 网卡 交换机 路由器

网络包只是一串二进制信息,需要将数字信号转换为电信号才能在网线上传输。网卡就是用于实现这一操作的,通过网卡驱动程序控制网卡。

交换机用于中途转发电信号。
首先,电信号到达网线接口,交换机里的模块进行接收,接下来交换机里的模块将电信号转换为数字信号。
然后,交换机根据 MAC 地址表查找 MAC 地址,然后将信号发送到相应的端口;如果MAC地址表中没找到指定地址,就会将包转发到除源端口外所有端口上。

网络包经过交换机后到达路由器,并由此转发到下一个路由器或者目标设备。那么路由器和交换机有什么区别呢?

  • 路由器是基于 IP 设计的,俗称三层网络设备,路由器的各个端口都具有 MAC 地址和 IP 地址
  • 交换机是基于以太网设计的,俗称二层网络设备,交换机的端口不具有 MAC 地址

路由器是这么工作的:
首先也是将电信号转换为数字信号,然后通过FCS进行错误校验。如果没问题则检查MAC头部中的接收方MAC地址,看看是不是发给自己的包,完成后去掉MAC头部。
接下来根据IP头部进行包的转发,根据路由表确定对方的IP地址,然后再根据ARP确定MAC地址,然后将数字信号转换为电信号从端口发送出去。
发送出去的网络包会通过交换机到达下一个路由器,以此类推,经过层层转发后,网络包最终到达目标地址。

根据上面的描述我们发现,在网络包传输的过程中,源 IP 和目标 IP 始终是不会变的,一直变化的是 MAC 地址,因为需要 MAC 地址在以太网内进行两个设备之间的包传输

5. 服务器处理请求并返回HTTP报文给客户端

数据包抵达服务器后,服务器会一层层拆开查看里面的核心内容:

  • 拆开MAC头,查看是否和服务器MAC地址吻合
  • 拆开IP头,查看IP地址是否吻合
  • 拆开TCP头,里面有序列号,需要看一看这个序列包是不是我想要的,如果是就放入缓存中然后返回一个 ACK,如果不是就丢弃。TCP头部里面还有端口号, HTTP 的服务器正在监听这个端口号。
  • 于是,服务器自然就知道是 HTTP 进程想要这个包,于是就将包发给 HTTP 进程。

服务器的 HTTP 进程看到,原来这个请求是要访问一个页面,于是就把这个网页封装在 HTTP 响应报文里。

响应报文也和发送报文时一样一层层组装好TCP,IP,MAC的头部,穿好头部衣服后,从网卡出去,交由交换机转发到出城的路由器,路由器就把响应数据包发到了下一个路由器,就这样跳啊跳。

最后跳到了客户端的城门把守的路由器,路由器扒开 IP 头部发现是要找城内的人,于是又把包发给了城内的交换机,再由交换机转发到客户端。

客户端收到了服务器的响应数据包后,同样也非常的高兴,客户能拆快递了!

6.浏览器解析渲染页面

  • 根据HTML解析DOM树,是一个深度优先遍历过程,该过程会被script标签阻塞
  • 根据CSS生成CSS规则树,同样遇到js会暂停执行
  • 结合DOM和CSSOM生成渲染树
  • layout阶段,根据渲染树计算每一个节点的位置和尺寸
  • paint阶段,根据计算好的信息绘制页面,将内容显示在屏幕上

7. 断开连接

也就是四次挥手,具体内容见另一篇博客