输入url到页面展示详解

1,959 阅读9分钟

浏览器从输入网址到网页展示总体分为一下几个步骤:

  1. DNS 解析:将域名解析成 IP 地址
  2. TCP 连接:TCP 三次握手
  3. 发送 HTTP 请求
  4. 服务器重定向
  5. 服务器处理请求并返回 HTTP 报文
  6. 浏览器解析渲染页面
  7. 断开连接:TCP 四次挥手

输入的url是什么

URI: Uniform Resource Identifier 统一资源标示符,标识一个资源

URL:Uniform Resource Location 统一资源定位符,提供找到资源的路径

URN: Universal Resource Name 统一资源名称,用特定命名空间的名字标识资源

URL和URN都是URI的子集

主要来分析url。一个很常见的url:www.baidu.com/, 格式为协议/域名

url格式标准为: scheme://host.domain:port/path/filename

  • scheme:定义因特网服务的类型。最常见的类型有 http,https,ftp、file
  • host:定义域主机(http 的默认主机是 www)
  • domain - 定义因特网域名,比如 baidu.com
  • port - 定义主机上的端口号(http 的默认端口号是 80)
  • path - 定义服务器上的路径(如果省略,则文档必须位于网站的根目录中)
  • filename - 定义文档/资源的名称

域名解析(DNS解析)

浏览器并不能直接通过域名找到对应的服务器,而是要通过 IP 地址,所有需要先将域名解析为ip地址,在通过ip地址找到服务器。

DNS 提供通过域名查找 IP 地址,或逆向从 IP 地址反查域名的服务。

浏览器查询ip步骤

  1. 先读取浏览器缓存。浏览器会按照一定的频率缓存 DNS 记录
  2. 查看本地 hosts 文件
  3. 系统缓存
  4. 读取路由器 DNS 缓存
  5. 本地 DNS 服务器
  6. DNS根服务器。本地DNS服务器找不到的话,就会向根服务器发出请求,进行递归查询(DNS 服务器先问根域名服务器.com 域名服务器的 IP 地址,然后再问.baidu 域名服务器,依次类推)

通过DNS预解析优化性能

  1. 用meta信息来告知浏览器, 当前页面要做DNS预解析

    <meta http-equiv="x-dns-prefetch-control" content="on" />
    
  2. 在页面header中使用link标签来强制对DNS预解析

    <link rel="dns-prefetch" href="http://bdimg.share.baidu.com" />
    

TCP连接(三次握手)

浏览器找到服务器的ip地址后,在发送数据之前会发起 TCP三次握手用以同步客户端和服务端的序列号和确认号,并交换 TCP 窗口大小信息。

三次握手过程

  1. 客户端发送一个带 SYN=1,Seq=X 的数据包到服务器端口
  2. 服务器发回一个带 SYN=1, ACK=X+1, Seq=Y 的响应包以示传达确认信息(确认客户端具有发送数据的能力)
  3. 客户端再回传一个带 ACK=Y+1, Seq=Z 的数据包,代表握手结束

三次握手的目的是为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。

发送 HTTP 请求

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

请求报文由请求行(request line)、请求头(header)、空行和请求正文四个部分组成

  • 请求行
GET /api/user/detail HTTP/1.1

请求行包含请求方法,url,协议版本。

  • 请求头

    请求头包含许多有关的客户端环境和请求正文的有用信息

    Accept: application/json, text/plain, */*
    Accept-Encoding: gzip, deflate
    Accept-Language: zh-CN,zh;q=0.9
    Connection: keep-alive
    Cookie: SESSION=ZmZkMDVkNzktMGMwZS00NTNkLTk3Y2MtZGUxNDA2MTY3MDBk
    Host: icsapi.aegs.ft.ztosys.com
    Origin: http://ics.aegs.ft.ztosys.com
    Referer: http://ics.aegs.ft.ztosys.com/
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) 
    
  • 空行

    请求头和请求正文之间是一个空行,它表示请求头已经结束,接下来的是请求正文

  • 请求正文

    若方法字段是GET,则此项为空,没有数据

    若方法字段是POST,则通常来说此处放置的就是要提交的数据

    productId=327&pageNum=1&pageSize=30
    

服务器重定向

重定向常见于:站点维护或停机期间的临时重定向和http请求转为https请求

重定向类别: 永久重定向: 301 、 308 临时重定向: 302 、303、307 特殊重定向: 300、304

拓展1:301与302的区别

302重定向只是暂时的重定向,搜索引擎会抓取新的内容而保留旧的地址,因为服务器返回302,所以,搜索搜索引擎认为新的网址是暂时的。而301重定向是永久的重定向,搜索引擎在抓取新的内容的同时也将旧的网址替换为了重定向之后的网址。

拓展2:前端重定向的方法

  1. HTML 重定向
 <meta http-equiv="Refresh" content="0; URL=http://example.com/" />
  1. JavaScript 重定向机制 window.location

服务器处理请求并返回 HTTP 报文

服务器收到了请求,进行处理,处理结束后会把它的处理结果返回,也就是返回一个HTPP响应。

响应报文由状态行(request line)、响应头部(header)、响应主体三个部分组成

  • 状态行

    状态行由协议版本、数字形式的状态代码、及相应的状态描述,各元素之间以空格分隔。

    HTTP/1.1 200 OK
    

    状态码:

    1xx:信息性状态码,表示服务器已接收了客户端请求,客户端可继续发送请求。

    2xx:成功状态码,表示服务器已成功接收到请求并进行处理。

    3xx:重定向状态码,表示服务器要求客户端重定向。

    ​ 301: Moved Permanently 永久性重定向

    ​ 302: Found 临时性重定向

    ​ 304: Not Modified 服务器内容没有更新,可以直接读取浏览器缓存

    4xx:客户端错误状态码,表示客户端的请求有非法内容。

    ​ 400: Bad Request 表示客户端请求有语法错误,不能被服务器所理解

    ​ 401: Unauthonzed 表示请求未经授权,该状态代码必须与 WWW-Authenticate 报头域一起使用

    ​ 403: Forbidden 表示服务器收到请求,但是拒绝提供服务,通常会在响应正文中给出不提供服务的原因

    ​ 404: Not Found 请求的资源不存在,例如,输入了错误的URL

    5xx:服务器错误状态码,表示服务器未能正常处理客户端的请求而出现意外错误。

    ​ 500: Internel Server Error 表示服务器发生不可预期的错误,导致无法完成客户端的请求

    ​ 503: Service Unavailable 表示服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常

  • 响应头部

    响应头部包含响应报文的附加信息,由 名/值 对组成

    Access-Control-Allow-Credentials: true
    Access-Control-Allow-Origin: http://ics.aegs.ft.ztosys.com
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Connection: keep-alive
    Content-Length: 240
    Content-Type: application/json;charset=UTF-8
    Date: Sat, 20 Feb 2021 02:22:39 GMT
    Expires: 0
    Pragma: no-cache
    Vary: Origin
    Vary: Access-Control-Request-Method
    Vary: Access-Control-Request-Headers
    X-Content-Type-Options: nosniff
    X-XSS-Protection: 1; mode=block
    
  • 响应主体

    服务器返回客户端的具体数据

浏览器解析渲染页面

当浏览器收到html文件后,尽管html文件还未传输完成,仍然开始解析html。解析的过程是从上而下,顺序解析。HTML对应于DOM的生成,CSS对应于CSSOM的生成,最终生成渲染树render-tree。再根据布局进行计算,最后GPU进行绘制。

ps:构建DOM树期间,如果遇到JS,阻塞DOM树及CSSOM树的构建,优先加载JS文件,加载完毕,再继续构建DOM树及CSSOM树。

渲染步骤如下:

  1. 根据 HTML 解析出 DOM 树

    DOM 树解析的过程是一个深度优先遍历。即先构建当前节点的所有子节点,再构建下一个兄弟节点。

  2. 根据 CSS 解析生成 CSS 规则树

  3. 结合DOM树和CSS规则树,生成渲染树

DOM 树和 CSS 规则树全部准备好了以后,浏览器才会开始构建渲染树。

  1. 布局计算

    通过渲染树中渲染对象的信息,计算出每一个渲染对象的位置和尺寸

  2. 根据计算好的信息绘制页面

    布局计算完成后,浏览器在页面渲染元素。经过渲染引擎处理后,整个页面就显示出来

    重绘:某个元素的背景颜色,文字颜色等,不影响元素周围或内部布局的属性,将只会引起浏览器的重绘。

    回流:某个元素的尺寸发生了变化,则需重新计算渲染树,重新渲染

    断开连接:TCP 四次挥手

    当数据传送完毕,需要断开 tcp 连接,此时发起 tcp 四次挥手

    1. 浏览器发送一个FIN,用来关闭浏览器到服务端的数据传送,浏览器进入FIN_WAIT_1状态。

    2. 服务端收到FIN后,发送一个ACK给浏览器,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),服务端进入CLOSE_WAIT状态。

    3. 服务端发送一个FIN,用来关闭服务端到浏览器的数据传送,服务端进入LAST_ACK状态。

    4. 浏览器收到FIN后,浏览器进入TIME_WAIT状态,接着发送一个ACK给服务端,确认序号为收到序号+1,服务端进入CLOSED状态,完成四次挥手。

    ACK:用于对收到的数据进行确认,所确认的数据由确认序列号表示。

    SYN:用作建立连接时的同步信号

    FIN:表示后面没有数据需要发送,通常意昧着所建立的连接需要关闭了。

    为什么建立连接是三次握手,而关闭连接却是四次挥手呢?

    这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。