题目② 浏览器输入url到页面加载过程发生了什么?

步骤

  1. DNS 查询

  2. 与服务器建立连接(TCP 连接)

  3. 请求响应(浏览器发起请求,服务器响应)

  4. 浏览器渲染(浏览器接收到响应的内容并渲染到页面)

  5. HTTP 连接断开

1 DNS 查询

1.1 DNS 解析流程

通过域名找 ip 的过程

DNS-域名解析过程.png

  • 首先,在 本地域名服务器 中根据域名查询 IP 地址,如果没有找到的情况下,本地域名服务器会向 根域名服务器 发送一个请求。

  • 如果根域名服务器也不存在该域名时,本地域名会向 com 顶级域名服务器(TLD) 发送一个请求,依次类推下去。

  • 直到最后本地域名服务器得到 google 的 IP 地址并把它缓存到本地,供下次查询使用。

1.2 DNS 的优化
  • 缓存

  • DNS 是存在着多级缓存,从离浏览器的距离排序的话,有以下几种:

    • 浏览器缓存

    • 系统缓存

    • Linux 操作系统

    • windows 操作系统

      C:WindowsSystem32driversetchosts

    • 路由器缓存

    • IPS 服务器缓存

    • 根域名服务器缓存

    • 顶级域名服务器缓存

    • 主域名服务器缓存。

1.3 DNS 负载均衡

不同的区域访问 Google 返回的 IP 是不一样的,甚至在同一个办公室访问 Google,返回回来的 IP 也有可能是不一样的

  • 使用了 DNS 负载均衡去支持超大量客户的请求

  • DNS 会根据你的位置或 IP 返回一个合适的 IP 给你用

2. 与服务器建立连接(TCP 连接)

DNS 解析返回域名的 IP 之后,接下来就是浏览器要和该 IP 建立 TCP 连接了

  • 为什么是 TCP 而不是 UCP?

    • 因为 HTTP 是基于 TCP 的
2.1 TCP/IP模型

TCP-IP模型.png

2.1.1 四层模型的概念
  • TCP/IP 想干嘛??

    • 实现用最少的资源,准确快速的把信息传送到对端去
  • 怎么充分利用资源?用资源怎么发送信息?怎么找到对端?怎么做到准确?怎么快速?怎么保证对端完整收到信息?

  • 怎样充分利用资源?

    • 物理层:无线铜线光纤损耗等
  • 怎样把信息传给设备?

    • 数据链路层:解决信息的封装问题,信息传送机制问题

随着入网设备越来越多,就需要被管理

  • 怎样快速准确找到对端?

    • 网络层用来解决网络管理的问题

      • IP 层是整个网络分层里承上启下的核心,主要解决两个问题:

        1. 编号
        2. 找人

        网络太大,人太多,认识不过来,所以要用 ip 地址给人编号

        编完号一个个找不可行 -> 路由技术

        • 网络层的关键是 路由技术,路由技术解决 怎样快速准确找到对端的问题
  • 怎样保证对端完整收到信息?

    • 传输层:传送速度的调节,传送信息的验证,传完信息的确认等,对应的TCP和UDP也是两种不同的实现思路
  • 怎么处理信息?

    • 应用层:不同的应用程序有着不同的通信协议

      • email -- SMTP

      • Web -- http

      • 文件传输 --ftp

      • 这些通信协议都工作在应用层

2.1.2 四层模型分别有哪些协议?
  1. 应用层

    • 常用的 HTTP HTTPS SSH Telnet 等都在应用层上
  2. 传输层

    • 最常见的 TCP 和 UDP 就在这里,TCP 三次握手也在这里
  3. 网络层

    • ICMP -- ping 命令就是用的 ICMP
  4. 链路层

    • 很底层

    • ARP -- 用来查找MAC地址

2.2 TCP 三次握手和四次挥手
2.2.1 TCP 三次握手
  • 所谓三次握手(Three-way Handshake),是指建立一个 TCP 连接时,需要客户端和服务器总共发送3个包。

  • 三次握手的目的是 连接服务器指定端口,建立 TCP 连接,并同步连接双方的序列号和确认号,交换 TCP 窗口大小信息。在 socket 编程中,客户端执行 connect() 时。将触发三次握手。

  1. 第一次握手(SYN=1, seq=x):

    • 客户端发送一个 TCP 的 SYN 标志位置1的包,指明客户端打算连接的服务器的端口,以及初始序号X,保存在包头的序列号(Sequence Number)字段里。

    • 发送完毕后,客户端进入 syn_send 状态。

  2. 第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1):

    • 服务器发回确认包(ACK)应答。即 SYN 标志位和 ACK 标志位均为1。服务器端选择自己 ISN 序列号,放到 Seq 域里,同时将确认序号(Acknowledgement Number)设置为客户的 ISN 加1,即 X+1。

    • 发送完毕后,服务器端进入 syn_rcvd 状态。

  3. 第三次握手(ACK=1,ACKnum=y+1):

    • 客户端再次发送确认包(ACK),SYN 标志位为0,ACK 标志位为1,并且把服务器发来 ACK 的序号字段+1,放在确定字段中发送给对方,并且在数据段放写 ISN 的 +1

    • 发送完毕后,客户端进入 established 状态,当服务器端接收到这个包时,也进入 established 状态,TCP 握手结束。

TCP三次握手.png

  • 为什么要三次握手?

    • 为了防止已失效的连接请求报文突然又传送到了服务器而产生错误。
  • 栗子

    • 客户端发出的第一个连接请求报文段并没有丢失而是在某个网络结点长时间滞留了,以致延误到连接释放以后的某个时间才到达服务器。

    • 本来这是一个早已失效的报文段,但服务器收到此失效的连接请求报文段后就误认为时客户端再次发出的一个新的连接请求,于是向客户端发出确认报文段,同意建立连接。

    • 假设不采用“三次握手”,那么只有服务器发出确认,新的连接就建立了。由于现在客户端并没有发出建立连接的请求,因此不会理睬服务器的确认,也不会像服务器发送数据,但是服务器以为新的运输连接已经建立,一直等待客户端发来数据。 这样,服务器的很多资源就白白浪费了。

    • 采用“三次握手”可以防止上述现象发生。客户端不会向服务器的确认发出确认,服务器由于收不到确认,就知道客户端并没有要求建立连接。

2.2.2 TCP 四次挥手
  • TCP 连接的拆除需要发送四个包,因此称为四次挥手(Four-way handshake),也叫做改进的三次握手。

  • 客户端或服务器均可主动发起挥手动作,在 socket 编程中,任何一方执行 close() 操作即可产生挥手操作。

  1. 第一次挥手(FIN=1,seq=x):

    • 假设客户端(主机1)想要关闭连接客户端(主机1)发送一个 FIN 标志位置为1的包表示自己已经没有数据可以发送了,但是仍然可以接受数据

    • 发送完毕后,客户端(主机1)进入 fin_wait_1 状态。

  2. 第二次挥手(ACK=1,ACKnum=x+1):

    • 服务器(主机2)确认客户端(主机1)的 FIN 包,发送一个确认包,表明自己接受到了客户端(主机1)关闭连接的请求,但还没有准备好关闭连接

    • 发送完毕后,服务器(主机2)进入 close_wait 状态,客户端(主机1)接收到这个确认包之后,进入 fin_wait_2 状态,等待服务器(主机2)关闭连接。

  3. 第三次挥手(FIN=1,seq=y):

    • 服务器(主机2)准备好关闭连接时,向客户端(主机1)发送结束连接请求,FIN 置为1。

    • 发送完毕后,服务器(主机2)进入 last_ack 状态,等待来自客户端(主机1)的最后一个ACK。

  4. 第四次挥手(ACK=1,ACKnum=y+1):

    • __客户端(主机1)__接收到来自服务器(主机2)的关闭请求,发送一个确认包,并进入 time_wait 状态,等待可能出现的要求重传的 ACK 包。

    • 服务器(主机2)接收到这个确认包之后,关闭连接,进入 closed 状态。

    • 客户端(主机1)等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器(主机2)的 ACK ,认为服务器端已经正常关闭连接,于是 自己也关闭连接,进入 closed 状态。

TCP四次挥手.png

  • 为什么是四次挥手

    • TCP 协议是一种面向连接的、可靠的、基于字节流的运输层通信协议。

    • TCP 是全双工模式,意味着

      • 当主机1发出 fin 报文段时,只是表示主机1已经没有数据要发送了,主机1告诉主机2,它的数据已经全部发送完毕了;但是,此时主机1还是可以接收来自主机2的数据;

      • 当主机2返回 ack 报文段时,表示它已经知道主机1没有数据发送了,但是主机2还是可以发送数据到主机1的;

      • 当主机2也发送了 fin 报文段时,就表示主机2也灭有数据要发送了,就会告诉主机1,它也没有数据要发送了,之后彼此就会中断这次 TCP 连接。

2.3 HTTPS 证书
  • 越来越多的网站开始使用 HTTPS(Apple 要求 App 都须用 HTTPS)。对于 HTTPS,需要有一个 SSL/TLS 的鉴权/认证,才能建立 TCP 链接。
2.3.1 HTTP和HTTPS的区别

HTTP和HTTPS的区别.png

3. 请求响应

3.1 HTTP methods 有哪几种,分别是什么?
3.1.1 restful 规范
  • 根据请求类型不同定义不同的接口

    • get 查

    • post 增

    • patch/put 改-> patch 字段部分修改

    • delete 删

  • 根据不同的地址实现不同的接口

    • get /goods 所有商品

    • post /goods 增加商品

    • get /goods/{id} 单个商品

    • delete /goods/{id} 删除商品

    • patch/put /goods/{id} 修改商品

3.1.2 http 的几种请求方法
  1. OPTIONS

    • 返回服务器针对特定资源所支持的 HTTP 请求方法,也可以利用向 web 服务器发送 ‘ * ’ 的请求来测试服务器的功能性
  2. HEAD

    • 向服务器索与GET请求相一致的响应,只不过响应体将不会被返回。

    • 这一方法可以再不必传输整个响应内容的情况下,就可以获取包含在响应小消息头中的元信息。

  3. GET

    • 向特定的资源发出请求。
  4. POST

    • 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。

    • 数据被包含在请求体中。

    • POST 请求可能会导致新的资源的建立和/或已有资源的修改。

  5. PUT

    • 向指定资源位置上传其最新内容
  6. DELETE

    • 请求服务器删除 Request-URL 所标识的资源
  7. TRACE

    • 回显服务器收到的请求,主要用于测试或诊断
  8. CONNECT

    • HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
3.1.3 HTTP 的put delete 等使用时需要注意什么?
  • 有的浏览器是不支持的,所以在使用和实现时需要仔细评估好自己客户端的能力。
3.1.4 HTTP 的 options 用来做什么?
  • OPTIONS一般用来获取目标资源的通信选项,例如确认允许的 HTTP Method.

  • OPTIONS一般用在哪里?

    • CORS
3.2 HTTP 响应报文常见状态码
3.2.1 状态码有3位数字
  • 1xx:指示信息 -- 表示请求已接收,继续处理

  • 2xx:成功 -- 表示请求已被成功接收、理解、接受

  • 3xx:重定向 -- 要完成请求必须进行更进一步的操作

  • 4xx:客户端错误 -- 请求有语法错误或请求无法实现

  • 5xx:服务器错误 -- 服务器未能实现合法的请求

3.2.2 常见的状态码
  • 200:响应成功

  • 302:跳转,跳转地址通过响应头的location属性指定

  • 400:客户端请求语法错误,不能被服务器识别

  • 403:服务器接收请求,但是拒绝提供服务(认证失败)

  • 404:请求资源不存在

  • 500:服务器内部错误

3.3 HTTP协议(包括HTTP/2.0)有了解吗?
3.3.1 HTTP2.0

HTTP2.0 大幅度的提高了 web 性能,在 HTTP1.1 完全语义兼容的基础上,进一步减少了网络的延迟。实现低延迟高吞吐量。对于前端开发者而言,减少了优化工作。

  • SPDY 协议--是对 HTTP 协议的增强

    • 核心思想:尽量减少 TCP 连接数
  • HTTP1.X 的缺点

    1. 一次只允许在一个 TCP 连接上发起一个请求,使用的流水线技术也只能部分处理请求并发,仍然会存在队列头阻塞问题--因此客户端在需要多次请求时,通常会采用建立多连接来减少延迟。

    2. 单向请求,只能由客户端发起。

    3. 请求报文和响应报文首部信息冗余量大。

    4. 数据未压缩,导致数据的传输量大。

3.3.2 二进制分帧

HTTP2.0 是怎样突破 HTTP1.1 的性能限制,实现高吞吐量呢?

  • 关键之一是在应用层(HTTP)和传输层(TCP)之间增加一个二进制分帧层

  • 关于帧:

    • HTTP2.0通信的最小单位,所有帧都共享一个8字节的首部,其中包含帧的长度、类型、标志、保留位,并且至少有标识出当前帧所属的流的标识符,帧承载着特定类型的数据,如HTTP首部、负荷、等等。

    • 消息:比帧大的通讯单位,是指逻辑上的HTTP消息,比如请求、响应等。由一个或多个帧组成

    • :比消息大的通讯单位。是TCP连接中的一个虚拟通道,可以承载双向的消息。每个流都有一个唯一的整数标识符

  • HTTP2.0中所有加强性能的核心是二进制传输

    • 因为引入了新的编码机制,所以传输的数据都会被分割,并采用二进制格式编码

在HTTP1.X中是通过 文本 传输数据的

3.3.3 首部压缩:专门为首部压缩而设计的HPACK算法
3.3.4 多路复用
  • HTTP2.0 中基于二进制分帧层,可以在共享TCP连接的基础上同时发送请求和响应。

    • HTTP 消息会被分解成独立的帧,而不破坏消息本身的语义,交错发出去;

    • 在另一端根据流的标识符和首部将他们重新组装起来

  • 通过该技术可以避免 HTTP 旧版本的队头阻塞问题,极大提高传输性能

3.3.5 请求优先级
  • 把 HTTP 消息分为很多独立帧之后,就可以通过优化这些帧的交错和传输顺序进一步优化性能。
3.3.6 服务器推送
  • 服务器可以对一个客户端请求发送多个响应,服务器向客户端推送资源无需客户端明确的请求。

  • 推送的缺点:所有推送的资源都必须遵守同源策略

3.4 Server 处理 HTTP 请求并返回 HTTP 报文

Server 返回的内容有哪些呢?这里只以 HTML 页面为例.一个页面一般包含 HTML、CSS、 JS、 图片等文件,那么浏览器收到这些文件后该如何渲染(render)他们呢?

4. 浏览器渲染

4.1 浏览器组成
  1. User Interface: UI组件包括地址栏,前进/后退按钮,书签菜单等。

  2. Browser Engine: 在UI组件和渲染引擎间采取一些 action.

  3. Rendering engine: 负责显示请求的内容。

    例如,如果是HTML页面,它将解析HTML,CSS,并将解析的内容显示在屏幕上。

    • 不同的浏览器使用不同的渲染引擎:

      • IE 使用 Trident

      • Firefox 使用 Gecko

      • Safari 使用 WebKit

      • Chrome 和 Opera(版本15开始)使用 Blink。它是基于 Webkit 开发的。

  4. Networking: 负责网络调用,例如 HTTP 请求。在不同的平台有不同的实

  5. UI backend: 主要用来绘画基本的 UI 元素,例如下拉框,Windows等。这个UI后台暴露一些通用的接口,并不依赖平台的。

  6. JavaScript interpreter: 用来解析和运行 JavaScript code。

  7. Data storage: 数据持久化的那一层。

    浏览器可能需要存储各种各样的数据,例如 Cookie。浏览器也得支持我们常用的 LocalStorage, IndexedDB,WebSQL以及FileSystem。

4.2 渲染页面的主要流程
  1. 渲染引擎解析文件

    • 渲染引擎解析 html 文档,将 html 包含的元素转化为一个个 dom,并构建为一个 dom树

    • 渲染引擎解析来自 css 文件或者行内样式数据,构建为一个 渲染树

  2. 布局

    • 渲染引擎会给每个 dom 元素安排精确的坐标,并根据坐标在屏幕上显示
  3. 遍历渲染树

    • ui bankend 层会将一个个 dom 元素在屏幕上绘画出来

    • 这是一个渐进的过程,边下载边解析,边解析边渲染

  • 渲染引擎是单线程工作的,除了网络操作,其他所有的都是单线程的

  • 网络操作则是由多个并列线程去执行,但数量一般限制在2-6个

  • 浏览器的主线程是一个无限的循环事件,而且一直保持进程 alive,一直等着各种事件,并处理他们

5. HTTP连接断开

CORS(Cross Origin Resource Sharing)跨域资源共享

是一个真正的ajax跨域请求方案

  // CORS简单请求
  let xhr=new XMLHttpRequest();
  xhr.onload=()=>{
    console.log('CORS',JSON.parse(xhr.responseText));
  }
  xhr.open('get','http://localhost:1910/goods',true);
  xhr.send();

1. 操作步骤

1.1 设置响应头
  • Access-Control-Allow-Origin
  • Access-Control-Allow-Headers
  • Access-Control-Allow-Methods
  Router.use((req,res,next)=>{
    //支持CORS跨域,只需要设置响应头
    res.header('Access-Control-Allow-Origin','*');
    // 跨域请求CORS中的预请求
    next();
  })
1.2 处理复杂跨域中的 OPTIONS 请求
  Router.use((req,res,next)=>{
    //支持CORS跨域,只需要设置响应头
    let currentOrigin=req.get('Origin');
    let allowOrigin=['http://localhost:8080','http://localhost:8081'];
    if(allowOrigin.includes(currentOrigin)){
      res.set({
        'Access-Control-Allow-Origin': currentOrigin,
        'Access-Control-Allow-Methods': 'GET, POST, PUT, PATCH, DELETE, OPTION',
        'Access-Control-Allow-Headers': 'Content-Type, Content-Length, Authorization, Accept, X-Requested-Width'
      })
    }
    // 跨域请求CORS中的预请求
    if(req.method=='OPTIONS'){
      res.sendStatus(200);//让options请求快速返回
    }else{
      next();
    }
  })
  • jsonP 与 CORS 都需要服务器的参与
原文地址:https://www.cnblogs.com/pleaseAnswer/p/15267400.html