zoukankan      html  css  js  c++  java
  • 浏览器工作原理与实践(三)之HTTP请求流程

    Set-Cookie: SERVERID=1fa1f330efedec1559b3abbcb6e30f50|1587649463|1587649463;Path=/
    Cache-Control:Max-age=2000
    GET /index.html HTTP1.1

    在浏览器实践与原理(二)之TCP协议介绍了TCP协议是如何保证数据传输完成性的。

    一个TCP链接包括了了建立连接、传输数据和断开连接三个阶段

    HTTP协议是建立在TCP连接基础之上的,HTTP是一种允许浏览器向服务器获取资源的协议是 Web的基础,通常由浏览器发起请求,用来获取不同类型的文件,例如HTML、CSS、JS、图片、文件、视频等。

    你是否有过下面这些疑问

    1. 为什么第一次打开一个站点速度很慢,当再次访问这个站点速度就很快了
    2. 当登陆过一个网址之后,下次再访问该站点就已经处于登录状态了

     这是怎么做到的呢?在今天这篇文章中,将通过分析一个HTTP请求过程中的每一步状态来了解完整的HTTP请求

    浏览器端发起HTTP请求流程

    如果你在浏览器地址栏里输入极客时间网站的地址:www.taobao.com

    接下来浏览器会完成哪些动作呢?一步一步来追踪一下

    1.构建请求

    首先,浏览器构建请求行信息(如下所示),构建好后,浏览器准备发起网络请求

    GET /index.html HTTP1.1

     2.查找缓存

     在真正发起网络请求前,浏览器会现在浏览器缓存中查询是否有要请求的文件。其中,浏览器缓存是一种在本地保存资源富文本,以供下次请求时直接使用的技术

     当浏览器发现请求的资源已经在浏览器缓存中存有副本,它会拦截请求,返回该资源的副本,并直接结束请求,而不会去资源服务器重新下载。这的好处:

    • 缓解服务器压力,提升性能(获取资源的耗时更短了)
    • 对于网站来说,缓存是实现快速资源加载的重要组成部分

    当然查找失败会进入网络请求

    3.准备IP地址和端口 

    在了解网络请求之前,我们需要先看看HTTP和TCP的关系。

    因为浏览器使用HTTP作为应用层协议,用来封装请求的文本信息;并使用TCP/IP作传输协议将它发送到网络上,所以在HTTP开始工作之前,浏览器需要通过TCP与服务器建立连接,也就是说HTTP的内容是通过TCP的传输数据阶段来实现的

     

    看上图,你可以思考这么一连串问题

    • HTTP网络请求的第一步是做什么呢?结合上图看是服务器和TCP链接
    • 那建立连接的信息都有了吗?在浏览器实践与原理(二)之TCP协议说到建立TCP连接的第一步需要准备IP和端口号
    • 那么怎么获取IP和端口号呢?这得看看我们现在有什么,我们有一个URL地址,是否可以利用URL地址来获取IP和端口信息呢

     数据包是通过IP地址传输给接收方的,由于IP地址是数字标识如:39.106.233.176,难以记忆,但使用域名(www.xxx.com)就方便多了,所以基于这个需求又出现了一个服务,

    负责把域名和IP地址做一一映射关系,这套域名映射为IP的系统就叫做域名系统,简称DNS

     所以,你会发现第一步浏览器会请求DNS返回域名对应的IP。浏览器还提供了DNS数据缓存服务,如果某个域名已经解析过了,浏览器会缓存解析结果,供下次使用

     拿到IP之后,接下来基因获取端口号了,如果URL没有特别指明端口号,那么HTTP协议默认是80端口。

    4.等待TCP队列

     准备好端口和IP地址,下一步就是建立TCP链接了吗?

    答案是不阔以哦,Chrome有个机制,同一个域名同时最多只能建立6个TCP连接,如果在同一个域名下同时有10个请求发生,那么其中四个请求会进入排队等待状态,直至请求完成

    如果请求数小于6,建立TCP连接

     5.建立TCP连接

    排队结束后,可以快乐的和服务器握手了,在HTTP工作之前,浏览器先通过TCP建立连接

     6.发送HTTP请求

     一旦建立了连接,浏览器就可以和服务器进行通信,而HTTP中的数据正是在这个通信过程中传输

    可以结合下图理解浏览器如何发送请求信息给服务器的 

     

    • 首先,浏览器会像服务器发送请求行,它包括了请求方法、请求URL和HTTP版本协议,发送请求行,就是告诉浏览器需要什么资源,最常用的是Get。比如,直接在浏览器地址栏输入极客时间的域名(https://time.geekbang.org/)就告诉浏览器要Get首页资源。
    • 另外一个常用的请求方法是POST,它用于发送一些数据给服务器,比如一个登陆网站,使用post方法,浏览器要准备数据给服务器,这里准备的数据通过请求体发送
    • 在浏览器发送请求命令之后,还要以请求头形式发送一些其他信息,把浏览器的一些基础信息告诉服务器,包括了浏览器的操作系统、浏览器内核等信息,以及当前请求的域名信息,浏览器的cookie等。

     服务器处理HTTP请求流程

    历经千辛万苦,HTTP的请求信息终于被送达了服务器,接下来,服务器会根据浏览器的请求信息准备相应内容

    1.返回请求 

    curl -i https://time.geekbang.org/

     这里加上了 i 是为了返回响应行、响应头和响应体的数据,返回的结果如下图:

     首先,服务器会返回响应行,包括协议版本和状态码

    但不是所有的请求都会被服务器成功处理的,那么一些无法处理或者处理出错的信息,怎么办呢?

    服务器会通过响应行的状态码来告诉浏览器它的处理结果,比如

    • 最常用的状态码是200,表示处理成功
    • 如果没有找到页面返回404

    随后,服务器也会随同响应向浏览器发送响应头。响应头包含了服务器自身的一些信息,比如服务器生成返回数据的时间、返回的数据类型,以及服务器在客户端保存的Cookie等信息。

    发送完响应头后,服务器可以继续发送响应体的数据

    2.断开连接

     通常情况下,一旦服务器向客户端返回了请求数据,就关闭TCP连接,不过浏览器或者服务器在其头信息加入了

    Connection: keep-alive

     那么TCP连接在发送后仍保持打开状态,这样浏览器就可以继续通过同一个TCP连接发送请求。

    保持TCP连接可以省去下次请求时需要建立连接的时间,提升资源加载速度

    比如同一个Web页面中内嵌的图片都来自同一个Web站点,如果初始化了一个持久连接,就可以复用该连接,以请求其他资源。

     3.重定向

    到这里似乎请求快结束了,不过还有一只能情况需要了解一下,比如你在浏览器中打开geekbang.org后,会发现最终打开的地址是https://www.geekbang.org/

    这两个URL之所以不一样,是因为涉及到了一个重定向操作,在控制台输入

    curl -I geekbang.org 

    注意这里输入的参数是-I,和-i不一样,-I是只需要获取响应头和响应数据,不需要获取响应体数据

     

    • 从上图可以看到,响应行返回的状态码是301,状态301是告诉浏览器,我需要重定向到另外一个地址
    • 需要重定向的网址正是包含在响应头的Location字段中的地址,并使用改地址重新导航

    注:不过也不要认为这种跳转是必然的,如果你打开 https://12306.cn会发现这个站点是打不开的,因为12306的服务器并没有处理跳转操作所以需要输入完整的https://www.12306.cn/才能打开页面

     问题解答

    为什么很多站点打开第二次速度会很快?

    如果打开第二次速度会很快,主要原因是第一次加载过程中,缓存了一些耗时的数据

    哪些数据会被缓存呢?

    从上面介绍请求路径看, DNS缓存和页面缓存资源这两块数据是会被浏览器缓存的

    看下浏览器资源缓存,如下图

    首先,来看下服务器是通过什么方式让浏览器缓存数据的?

    从上图可以看出第一次请求可以看出,当服务器返回HTTP响应头给浏览器时,浏览器通过响应头中的Cache-Control字段来设置一个缓存的过期时长,而这个时长是通过Max-age参数来设置的,如上图设置缓存过期时间是2秒 

    Cache-Control:Max-age=2000

     这也就意味着,在该缓存资源还未过期的情况下,如果再次请求资源,会直接返回缓存中的资源给浏览器

     但如果资源过期了,浏览器会继续发起网络请求,并且在HTTP请求头带上

    If-None-Match:"4f80f-13c3alxb12a"

     服务器收到请求后,会根据If-None-Match的值来判断请求的资源是否有更新

    • 如果没有更新,就返回304状态码,相当于告诉浏览器:“z这个缓存可以继续使用,这次就不重复发送数据给你了”
    • 如果资源有更新,服务器就直接返回最新资源给浏览器

     简单来说,浏览器第二次访问能够秒开,是因为这些网站把很多资源都缓存在了本地,浏览器缓存直接使用本地副本回应请求,不会产生真正的网络请求

    2.登录状态是如何保持的?

    • 用户打开登录界面,在登录框填入用户名和密码,点击登录按钮,调用post提交登录信息给服务端
    • 服务器收到浏览器提交的信息之后,查询后台,验证用户信息是否正确,如果正确,会生成一段表示用户身份的字符串,并把该字符串写到响应头的Set-cookie字段,发送给浏览器 
    • 浏览器在接受到服务器响应后,开始解析响应头,如果遇到响应头含义Set-Cookie字段的情况,浏览器会把这个字段信息保存到本地
    • 当用户再次访问时浏览器会发起HTTP请求,但在发起请求之前,浏览器会之前保存的Cookie数据,并把数据写到请求头里的Cookie字段里
    • 服务器在收到HTTP请求头数据之后,就会查找包含用户Cookie的信息,然后查询后台,判断用户已是登录状态,生成有该用户的页面数据,发送给浏览器
    • 浏览器在接收到该含有当前用户的页面数据后,就可以正确展示登录状态信息了
    Set-Cookie: SERVERID=1fa1f330efedec1559b3abbcb6e30f50|1587649463|1587649463;Path=/

     通过上面这个流程可以知道浏览器页面状态是通过Cookie实现的

     如图

     

    简单地说,如果服务器端发送的响应头内有 Set-Cookie 的字段,那么浏览器就会将该字段的内容保持到本地当下次客户端再往该服务器发送请求时,客户端会自动在请求头中加入 Cookie 值后再发送出去。服务器端发现客户端发送过来的 Cookie 后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录,最后得到该用户的状态信息。

    下图帮你理解 HTTP请求示意图

     

    在 PDFlux 中打开
    无数据
  • 相关阅读:
    130517Dev GridControl建立多行复杂表头(Banded View)时,统计列与对应列无法对齐的解决办法
    C&C++标准库
    Linux操作系统下的多线程编程详细解析
    Ubuntu12.04用户以root身份登录
    ubuntu永久修改主机名
    linux信号 linux signal
    淘宝api 登录验证
    淘宝开店 防骗 易赛加款诈骗|冲q币恶意差评
    面试..
    test
  • 原文地址:https://www.cnblogs.com/cuixiaohua/p/12764058.html
Copyright © 2011-2022 走看看