整体流程

域名解析 -> 与服务器建立连接 -> 发起HTTP请求 -> 服务器相应HTTP请求 -> 浏览器得到html代码 -> 浏览器解析html文件,创建DOM树 -> 解析CSS,创建CSS对象模型 -> 将CSS与DOM合并,构建渲染树(rendering tree)-> 布局和绘制

域名解析

  1. 首先会从浏览器自身DNS搜索,找到并且没有过期,则跳过域名解析过程,否则进行下一步

    Chrome的DNS缓存大概1分钟缓存,且只能容纳100条;IE为30分钟;FireFox也为1分钟

  2. 从系统本地缓存DNS中搜索(使用 ipconfig /dispalydns),这个缓存有效期一般和DNS服务器返回的TTL时间有关,如果搜索到则跳过解析过程,否则进行下一步

  3. 查看系统的hosts文件中有没有该域名对应的ip地址,如果有,则跳过解析过程,否则进行下一步

  4. 向本地配置的首选DNS服务器发起域名解析,DNS服务器则会返回对应的ip地址

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

  1. A 的 TCP 向 B 发出连接请求报文段,其首部中的同步比特 SYN 应置为1,并选择序号 x,表明传送数据时的第一个数据字节的序号是 x(设置初始段序号SEQ = x ,例如SEQ = 26 500)

  2. B 的 TCP 收到连接请求报文段后,如同意,则发回确认。B 在确认报文段中应将 SYN 置为 1,其确认号ACK应为 x + 1(ACK 26 501),同时也给出自己的选择序号 y(设置初始段序号SEQ = y ,例如SEQ = 29 010)。

  3. A 收到此报文段后,向 B 给出确认,其确认号应为 y + 1(ACK = 29011)。

衍生问题:

  1. TCP 为什么是三次握手,而不是两次或四次?

TCP 需要 seq 序列号来做可靠重传或接收,而避免连接复用时无法分辨出 seq 是延迟或者是旧链接的 seq,因此需要三次握手来约定确定双方的 ISN(初始 seq 序列号)。

知乎上有一个特别搞笑的图片,感觉更生动的描述了三次握手的情况:

不过上面的图其实是有点问题的,因为如果第一次握手失败,A其实应该超时重发,而不会发送数据请求,其实理解起来很简单:

A–请求–>B

A<–确认–B

A<–请求–B

A–确认–>B

中间两次可以一起返回,所以是三次

  1. 为什么HTTP协议要基于TCP来实现?

在Internet中所有的传输都是通过TCP/IP进行的,HTTP协议作为TCP/IP模型中应用层的协议也不例外,TCP是一个端到端的可靠的面向连接的协议,所以HTTP基于传输层TCP协议不用担心数据的传输的各种问题。

  1. TCP协议工作在哪一层?
OSI七层模型 TCP/IP概念层模型 功能 TCP/IP协议族
应用层 应用层 文件传输、电子邮件、文件服务、虚拟终端 TFTP、HTTP、SNMP、FTP、SMTP、DNS、Telnet
表示层 应用层 数据格式化、代码转换、数据加密
会话层 应用层 解除或建立与别的接点的联系
传输层 传输层 提供端对端的接口 TCP、UDP
网络层 网络层 为数据包选择路由 IP、ICMP、RIP、OSPF、EGP、IGMP
数据链路层 链路层 传输有地址的帧以及错误检测功能 SLIP、CSLIP、PPP、ARP、RARP、MTU
物理层 链路层 以二进制数据形式在物理媒体上传输数据 ISO2110、IEEE802、IEEE802.2
  1. HTTP3.0为什么选用UDP协议?

来源:https://blog.csdn.net/lunahaijiao/article/details/117267858

因为TCP协议存在以下几个问题:

  • 通信时间较长

    • RTT(Round-Trip Time),往返时间长,即A->B B->A A-B,需要三次握手,那么相当于一次TCP连接需要1.5RTT

    • HTTP通信时间,A->B B->A,但是由于TCP第三次握手不需要服务器返回,故这里可以省略0.5RTT

    • HTTPS通信时间,目前主流浏览器几乎只支持加密的HTTP/2,所以HTTP/2大概率都是HTTPS协议,而HTTPS协议,其实是指HTTP + SSL/TLS,所以需要额外的TLS连接时间,而TLS连接需要4次握手:客户端发送随机数、TLS版本号、支持的密码套件列表给服务器 -> 服务器收到随机数,自己也生成一个随机数,并根据客户端需求的协议和机密方式来发送紫的证书 -> 客户端收到证书并验证有效性,通过后在生成一个随机数,通过服务端证书的公钥加密这个随机数给服务器 -> 服务器收到加密过的随机数并使用私钥解密并获得第三个随机数,然后即可使用这三个随机数来按照之前约定的方式加密生成秘钥,接下来的会话就会使用这个秘钥进行加密解密

所以HTTPS的通信时间总和为: TCP 建立连接时间 + TLS 连接时间 + HTTP交易时间 = 1.5 RTT + 2 RTT + 0.5 RTT = 4 RTT

如果服务器距离客户端较远,一个RTT通常延时在200ms以上,那么光是通信所需耗费的时间就已经接近1s,已经严重影响用户体验了。

  • 队头阻塞问题相较于 HTTP/1.1 更严重

因为 HTTP/2 使用了多路复用,一般来说同一域名下只需要使用一个 TCP 连接。当这个连接中出现了丢包的情况,那就会导致 HTTP/2 的表现情况反倒不如 HTTP/1 了。

因为在出现丢包的情况下,整个 TCP 都要开始等待重传,也就导致了后面的所有数据都被阻塞了。但是对于 HTTP/1 来说,可以开启多个 TCP 连接,出现这种情况反到只会影响其中一个连接,剩余的 TCP 连接还可以正常传输数据。

所以,谷歌基于这个问题,对UDP进行了改造,改造的原因如下图:

TCP协议应用广泛,兼容困难,其协议栈又是Linux内部的重要部分,修改和升级成本非常大,所以,谷歌决定在 UDP 基础上改造一个具备 TCP 协议优点的新协议也就顺理成章了,这个新协议就是 QUIC 协议(Quick UDP Internet Connection),并且使用在了 HTTP/3 上,当然 HTTP/3 之前名为 HTTP-over-QUIC,从这个名字中我们也可以发现,HTTP/3 最大的改造就是使用了 QUIC。

QUIC 虽然基于 UDP,但是在原本的基础上新增了很多功能,比如多路复用、0-RTT、使用 TLS1.3 加密、流量控制、有序交付、重传等等功能。

发起HTTP请求

  • 属于应用层的协议,配合TCP/IP使用

  • 请求方法有8种:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE。最常的两种GET和POST,如果是RESTful接口的话一般会用到GET、POST、DELETE、PUT。

  • 请求地址:<协议>://<主机>:<端口>/<路径>

  • 常见的Request Header:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Host: www.test.com/  //请求的目标域名和端口号
    Origin: http://localhost:8081/ //请求的来源域名和端口号 (跨域请求时,浏览器会自动带上这个头信息)
    Referer: https:/localhost:8081/link?query=xxxxx //请求资源的完整URI
    User-Agent //浏览器信息
    Cookie: //当前域名下的Cookie
    Accept: text/html,image/apng //代表客户端希望接受的数据类型是html或者是png图片类型
    Accept-Encoding: gzip, deflate //代表客户端能支持gzip和deflate格式的压缩
    Accept-Language: zh-CN,zh;q=0.9 //代表客户端可以支持语言zh-CN或者zh(值得一提的是q(0~1)是优先级权重的意思,不写默认为1,这里zh-CN是1,zh是0.9)
    Connection: keep-alive //告诉服务器,客户端需要的tcp连接是一个长连接
    If-None-Match //如果内容未改变返回304代码,对应Etag
    If-Modified-Since //对应last-midified,未被修改则返回304代码
  • 常见的Response Header:

1
2
3
4
5
6
7
8
9
Date: //服务端发送资源时的服务器时间
Expires: //缓存过期时间
Cache-Control: no-cache // 缓存方式
Etag // 文件内容hash
Last-Modified //最近一次文件修改时间
Content-Type: text/html; charset=utf-8 //编码格式
Content-Encoding: gzip //采用gzip对资源进行解码
Connection: keep-alive //tcp是长连接
Set-Cookie //设置Http Cookie
  • 常见状态码:

    • 1xx:指示信息–表示请求已接收,继续处理。

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

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

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

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

浏览器拿到HTML文件

未完待续…