大致流程
- URL 解析
- DNS 解析
- 建立连接
- 五层协议
- TCP 三次握手
- TCP 四次挥手
- 可靠传输
- 请求交互
- HTTP 报文
- 长连接和短连接
- HTTP 和 HTTPS
- HTTP2.0
- Cookie 和 Session
- GET 和 POST
- 渲染页面
URL 解析
浏览器是多进程的,有一个主控进程,以及每一个 tab 页面都会新开一个进程(某些情况下多个tab会合并进程)。
每一个 tab 页面可以看作是浏览器内核进程,然后这个进程是多线程的,它有几大类子线程:
- GUI 渲染线程
- JS 引擎线程
- 事件触发线程
- 定时触发器线程
- 网络请求线程
以上是浏览器的简单模型,输入 URL 后,浏览器会对其进行解析(URL的本质是统一资源定位符),URL 一般包括以下几个部分:
- protocol,协议头,譬如有 http,ftp 等
- host,主机域名或 IP 地址
- port,端口号
- path,目录路径
- query,即查询参数
- fragment,即#后的hash值,一般用来定位到某个位置
每次网络请求时都需要开辟单独的线程进行,譬如如果 URL 解析到 HTTP 协议,就会新建一个网络线程去处理资源下载。浏览器会根据解析出得协议,开辟一个网络线程,前往请求资源。
DNS 解析
“域名系统(DNS,Domain Name System )是建立在分布式数据库上的分层命名系统。该系统将域名转换为 IP 地址,并可以将域名分配给 Internet 组资源和用户,无论实体的物理位置如何。”
输入的 URL 通常是域名,需要通过 DNS 解析将其转换成 IP 地址。大致流程是:
- 如果浏览器有缓存,直接使用浏览器缓存,否则使用本机缓存,再没有的话就是用 HOST。
- 如果本地没有,就向 DNS 域名服务器查询(浏览器缓存 - 操作系统缓存 - 路由器缓存 - ISP DNS 缓存 - 根域名服务器等如果存在缓存,会直接使用这些缓存),查询到对应的 IP。
浏览器向本地 DNS 服务器发起请求,由于本地 DNS 服务器没有缓存不能直接将域名转换为 IP 地址,需要采用递归或者迭代(依次遍历)查询的方式依次向根域名服务器、顶级域名服务器、权威域名服务器发起查询请求,直至找到一个或一组 IP 地址,返回给浏览器。
递归方式:一路查下去中间不返回,得到最终结果才返回信息(浏览器到本地DNS服务器的过程)
迭代方式:本地 DNS 服务器到根域名服务器查询的方式。
建立连接
五层协议
网络通信工作可以简要地分为以下五层:
- 应用层:应用进程间通信和交互的规则,支持万维网应用的 HTTP 协议和支持电子邮件的 SMTP 协议属于此层。应用层交互的数据单元成为报文。
- 运输层:像两台主机中进程之间的通信提供通用的数据传输服务,主要使用以下两种协议:
- 传输控制协议(TCP, Transmission Control Protocol),面向连接的、可靠的数据传输服务,其数据传输单位是报文段。
- 用户数据报协议(UDP, User Datagram Protocol),提供无连接的,尽最大努力的数据传输服务,不保证数据传输的可靠性,其数据传输单位是用户数据报。
- 网络层:为分组交换网上的不同主机提供通信服务。在 TCP/IP 体系中,网络层使用 IP 协议,因此分组也叫做 IP 数据报。
- 数据链路层:主机之间的数据传输总是在一段一段的链路上传送的。在相邻两个节点之间传输是,数据链路层将网络层交下来的 IP 数据报组装成帧,在两个相邻节点间的链路上传送帧。每一帧包括数据和必要的控制信息。
- 物理层:物理层上所传数据单位是比特。物理层下面的物理媒介如光缆、无线信道等通常被当成第 0 层。
OSI 七层协议中,在应用层和运输层中间依次有表示层(数据格式化、加密等)、会话层(解除或建立与别的节点的联系)。
运输层中 TCP 协议和 UDP 协议的区别如下表所示:
类型 | 是否面向连接 | 可靠性 | 形式 | 效率 | 占用资源 | 场景 |
---|---|---|---|---|---|---|
TCP | 面向连接 | 可靠 | 字节流 | 慢 | 多 | 要求数据可靠的常见,如文件传输 |
UDP | 无连接 | 不可靠 | 数据报文段 | 快 | 少 | 要求速度快,如直播、实时游戏等 |
TCP 三次握手
客户 A:连接请求。
服务器 B:如果同意连接,向 A 发送确认。
客户 A:收到 B 的确认报文后,再次向 B 发送确认。A 进入连接成功状态,B 收到确认后也进入连接成功状态。
由此成功建立连接。
第三次握手的意义在于,防止已失效的连接请求突然传到了 B 而产生错误。如果 A 第一次发送的报文由于某些原因滞留了,延误到连接释放之后才到达 B。对于 A 来说这已经是失效的报文,但 B 收到此连接请求后,会向 A 发送同意连接,然后认为建立了新的连接,此时 A 显然不会理睬 B,因为连接早就结束了。此种情况会导致 B 的资源闲置浪费。
TCP 四次挥手
客户 A:请求关闭连接,进入终止等待 1。
服务器 B:收到请求,发送确认,进入关闭等待状态。(A 收到确认,进入终止等待 2,并等待 B 发送连接释放报文)。
服务器 B:发送连接释放报文,进入最后确认状态。
客户 A:收到连接释放报文,发送确认,进入有限时间等待,超时自动关闭。B 收到确认,关闭连接。
可靠传输
- 应用数据被分割成 TCP 认为最适合发送的数据块。
- TCP 给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。
- 校验和: TCP 将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。
- TCP 的接收端会丢弃重复的数据。
- 流量控制: TCP 连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议。 (TCP 利用滑动窗口实现流量控制)
- 拥塞控制: 当网络拥塞时,减少数据的发送。
- ARQ协议: 也是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组。
- 超时重传: 当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。
请求交互
HTTP 报文
报文一般包括了:通用头部,请求/响应头部,请求/响应体。
通用头部
Request Url: 请求的web服务器地址
Request Method: 请求方式
(Get、POST、OPTIONS、PUT、HEAD、DELETE、CONNECT、TRACE)
Status Code: 请求的返回状态码,如 200 代表成功
Remote Address: 请求的远程服务器地址(会转为IP)
1xx——指示信息,表示请求已接收,继续处理
2xx——成功,表示请求已被成功接收、理解、接受
3xx——重定向,要完成请求必须进行更进一步的操作
4xx——客户端错误,请求有语法错误或请求无法实现
5xx——服务器端错误,服务器未能实现合法的请求
200——表明该请求被成功地完成,所请求的资源发送回客户端
304——自从上次请求后,请求的网页未修改过,请客户端使用本地缓存
400——客户端请求有错(譬如可以是安全模块拦截)
401——请求未经授权
403——禁止访问(譬如可以是未登录时禁止)
404——资源未找到
500——服务器内部错误
503——服务不可用
请求/响应头部
常用请求头部:
Accept: 接收类型,表示浏览器支持的 MIME 类型(对标服务端返回的 Content-Type)
Accept-Encoding:浏览器支持的压缩类型,如 gzip 等,超出类型不能接收
Content-Type:客户端发送出去实体内容的类型
Cache-Control: 指定请求和响应遵循的缓存机制,如 no-cache
If-Modified-Since:对应服务端的 Last-Modified,用来匹配看文件是否变动,只能精确到 1s 之内
Expires:缓存控制,在这个时间内不会请求,直接使用缓存,http1.0,而且是服务端时间
Max-age:代表资源在本地缓存多少秒,有效时间内不会请求,而是使用缓存
If-None-Match:对应服务端的 ETag,用来匹配文件内容是否改变(非常精确)
Cookie: 有 cookie 并且同域访问时会自动带上
Connection: 当浏览器与服务器通信时对于长连接如何进行处理,如 keep-alive
Host:请求的服务器 URL
Origin:最初的请求是从哪里发起的(只会精确到端口),Origin 比 Referer 更尊重隐私
Referer:该页面的来源 URL (适用于所有类型的请求,会精确到详细页面地址,csrf拦截常用到这个字段)
User-Agent:用户客户端的一些必要信息,如UA头部等
常用响应头部:
Access-Control-Allow-Headers: 服务器端允许的请求 Headers
Access-Control-Allow-Methods: 服务器端允许的请求方法
Access-Control-Allow-Origin: 服务器端允许的请求 Origin 头部(譬如为*)
Content-Type:服务端返回的实体内容的类型
Date:数据从服务器发送的时间
Cache-Control:告诉浏览器或其他客户,什么环境可以安全的缓存文档
Last-Modified:请求资源的最后修改时间
Expires:应该在什么时候认为文档已经过期,从而不再缓存它
Max-age:客户端的本地资源应该缓存多少秒,开启了 Cache-Control 后有效
ETag:请求变量的实体标签的当前值
Set-Cookie:设置和页面关联的 cookie,服务器通过这个头部把 cookie 传给客户端
Keep-Alive:如果客户端有 keep-alive,服务端也会有响应(如 timeout=38)
Server:服务器的一些相关信息
长连接和短连接
tcp/ip层面:
长连接:一个 tcp/ip 连接上可以连续发送多个数据包,在tcp连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接,一般需要自己做在线维持(类似于心跳包)。
短连接:通信双方有数据交互时,就建立一个 tcp 连接,数据发送完成后,则断开此 tcp 连接。
http层面:
http1.0 中,默认使用的是短连接,也就是说,浏览器没进行一次 http 操作,就建立一次连接,任务结束就中断连接,譬如每一个静态资源请求时都是一个单独的连接。
http1.1 起,默认使用长连接,使用长连接会有这一行 Connection: keep-alive,在长连接的情况下,当一个网页打开完成后,客户端和服务端之间用于传输 http 的 tcp 连接不会关闭,如果客户端再次访问这个服务器的页面,会继续使用这一条已经建立的连接。
keep-alive 不会永远保持,它有一个持续时间,一般在服务器中配置(如apache),另外长连接需要客户端和服务器都支持时才有效。
HTTP 和 HTTPS
- 端口 :HTTP的URL由“http://”起始且默认使用端口80,而HTTPS的URL由“https://”起始且默认使用端口443。
- 安全性和资源消耗: HTTP协议运行在TCP之上,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。HTTPS是运行在SSL/TLS之上的HTTP协议,SSL/TLS 运行在TCP之上。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。所以说,HTTP 安全性没有 HTTPS高,但是 HTTPS 比HTTP耗费更多服务器资源。
HTTP2.0
显著不同
http1.1中,每请求一个资源,都是需要开启一个tcp/ip连接的,所以对应的结果是,每一个资源对应一个tcp/ip请求,由于tcp/ip本身有并发数限制,所以当资源一多,速度就显著慢下来
http2.0中,一个tcp/ip请求可以请求多个资源,也就是说,只要一次tcp/ip请求,就可以请求若干个资源,分割成更小的帧请求,速度明显提升。
特性
多路复用(即一个tcp/ip连接可以请求多个资源)
首部压缩(http头部压缩,减少体积)
二进制分帧(在应用层跟传送层之间增加了一个二进制分帧层,改进传输性能,实现低延迟和高吞吐量)
服务器端推送(服务端可以对客户端的一个请求发出多个响应,可以主动通知客户端)
请求优先级(如果流被赋予了优先级,它就会基于这个优先级来处理,由服务器决定需要多少资源来处理该请求。)
Cookie 和 Session
Cookie 和 Session 都是用来跟踪浏览器用户身份的会话方式,但是两者的应用场景不太一样。
Cookie 一般用来保存用户信息,比如保存已经登录过得用户信息,下次访问网站的时候页面可以自动帮你登录的一些基本信息给填了;一般的网站都会有保持登录也就是说下次你再访问网站的时候就不需要重新登录了,这是因为用户登录的时候我们可以存放了一个 Token 在 Cookie 中,下次登录的时候只需要根据 Token 值来查找用户即可(为了安全考虑,重新登录一般要将 Token 重写);登录一次网站后访问网站其他页面不需要重新登录。
Session 的主要作用就是通过服务端记录用户的状态。 典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了。
Cookie 存储在客户端中,而 Session 存储在服务器上,相对来说 Session 安全性更高。
如果使用 Cookie 的一些敏感信息不要写入 Cookie 中,最好能将 Cookie 信息加密然后使用到的时候再去服务器端解密。
GET 和 POST
作用
GET 用于获取资源,而 POST 用于传输实体主体。
参数
GET 和 POST 的请求都能使用额外的参数,但是 GET 的参数是以查询字符串出现在 URL 中,而 POST 的参数存储在实体主体中。不能因为 POST 参数存储在实体主体中就认为它的安全性更高,因为照样可以通过一些抓包工具(Fiddler)查看。
因为 URL 只支持 ASCII 码,因此 GET 的参数中如果存在中文等字符就需要先进行编码。例如 中文 会转换为 %E4%B8%AD%E6%96%87,而空格会转换为 %20。POST 参数支持标准字符集。
安全
安全的定义是:HTTP 方法不会改变服务器状态,也就是说它只是可读的。
GET 方法是安全的,而 POST 却不是,因为 POST 的目的是传送实体主体内容,这个内容可能是用户上传的表单数据,上传成功之后,服务器可能把这个数据存储到数据库中,因此状态也就发生了改变。
安全的方法除了 GET 之外还有:HEAD、OPTIONS。
不安全的方法除了 POST 之外还有 PUT、DELETE。
幂等性
幂等的 HTTP 方法,同样的请求被执行一次与连续执行多次的效果是一样的,服务器的状态也是一样的。换句话说就是,幂等方法不应该具有副作用(统计用途除外)。
所有的安全方法也都是幂等的。
在正确实现的条件下,GET,HEAD,PUT 和 DELETE 等方法都是幂等的,而 POST 方法不是。
可缓存
如果要对响应进行缓存,需要满足以下条件:
- 请求报文的 HTTP 方法本身是可缓存的,包括 GET 和 HEAD,但是 PUT 和 DELETE 不可缓存,POST 在多数情况下不可缓存的。
- 响应报文的状态码是可缓存的,包括:200, 203, 204, 206, 300, 301, 404, 405, 410, 414, and 501。
- 响应报文的 Cache-Control 首部字段没有指定不进行缓存。
渲染页面
资源到达浏览器后,渲染步骤大致可以分为以下几步:
- 解析 HTML,构建 DOM 树
- 解析 CSS,生成 CSS 规则树
- 合并 DOM 树和 CSS 规则,生成 render 树
- 布局 render 树(Layout/reflow),负责各元素尺寸、位置的计算
- 绘制 render 树(paint),绘制页面像素信息
- 浏览器会将各层的信息发送给 GPU,GPU 会将各层合成(composite),显示在屏幕上。
参考
- 谢希仁. 计算机网络(第7版)[M]. 电子工业出版社. 2017.
- 面试环节:在浏览器输入 URL 回车之后发生了什么?(超详细版)
- 从输入URL到页面加载的过程?如何由一道题完善自己的前端知识体系!