HTTP即超文本传输协议(HyperText Transfer Protocol) 是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应(百度百科)。
通常由浏览器发起请求,用来获取不同类型的文件,例如 HTML 文件、CSS 文件、JavaScript 文件、图片、视频等。此外HTTP 也是浏览器使用最广的协议
首先看下下面这张详细的“HTTP请求示意图”,用来展现浏览器中的 HTTP 请求所经历的各个阶段
接下来详细了解下HTTP的完整请求流程
1.构建请求
首先,浏览器构建请求行信息(如下所示),构建好后,浏览器准备发起网络请求。
GET /index.html HTTP1.1
2. 查找缓存
真正发起网络请求之前,浏览器会先在浏览器缓存中查询是否有要请求的文件。其中浏览器缓存是一种在本地保存资源副本,以供下次请求时直接使用的技术。
当浏览器发现请求的资源已经在浏览器缓存中时,就不会在继续发送请求而是直接返回缓存中的资源,如果查找失败则才会进入网络请求的过程。样做的好处有:
- 缓解服务器端压力,提升性能,因为获取资源的耗时更短了
- 对于网站来说,缓存是实现快速资源加载的重要组成部分
关于浏览器资源缓存的详细内容可以参考我的这篇文章:浏览器静态资源缓存机制(网络篇)
3. 准备 IP 地址和端口
浏览器使用HTTP协议作为应用层协议,用来封装请求的文本信息;并使用TCP/IP作为传输层协议将它发送到网络上,所以在 HTTP 工作开始之前,浏览器需要通过 TCP 与服务器建立连接。下图描述了TCP和HTTP的关系。
我们通过TCP下的单个数据包的传输流程来看下建立TCP连接需要那些信息
从图中可以看到建立TCP连接的第一步就是需要准备IP地址和端口号,那怎么获取 IP 地址和端口号呢?这得看看我们现在有什么,我们有一个 URL 地址,那么是否可以利用 URL 地址来获取 IP 和端口信息呢?
数据包都是通过 IP 地址传输给接收方的。由于IP 地址是数字标识,但是IP 地址难以记忆,但使用域名就好记多了,所以基于这个需求又出现了一个服务,负责把域名和 IP 地址做一一映射关系。这套域名映射为 IP 的系统就叫做“域名系统”,简称DNS(Domain Name System)。
所以第一步浏览器会请求 DNS 返回域名对应的 IP。当然浏览器还提供了DNS 数据缓存服务,如果某个域名已经解析过了,那么浏览器会缓存解析的结果,以供下次查询时直接使用,这样也会减少一次网络请求。
拿到 IP 之后,接下来就需要获取端口号了。通常情况下,如果 URL 没有特别指明端口号,那么 HTTP 协议默认是 80 端口。
4. 等待 TCP 队列
把端口和 IP 地址都准备好之后还不能直接建立TCP连接,到因为Chrome 有个机制,同一个域名同时最多只能建立6个 TCP 连接,如果在同一个域名下同时有10个 请求发生,那么其中4个请求会进入排队等待状态,直至进行中的请求完成。 如果当前请求数量少于6,会直接进入下一步,建立 TCP 连接。
5. 建立 TCP 连接
排队等待结束之后,就可以和服务器建立TCP连接了。 三次握手建立TCP连接的过程可参考:TCP三次握手
关于网络层协议的详细内容可以参考这篇文章:图解OSI七层协议模型、TCP/IP四层模型、五层协议体系结构
6. 发送 HTTP 请求
一旦建立了 TCP 连接,浏览器就可以和服务器进行通信了。而 HTTP 中的数据正是在这个通信过程中传输的。
可以结合下图来理解浏览器发送给服务器的请求信息
首先发送请求行,请求行是告诉服务器浏览器需要什么资源,最常用的请求方法是Get,还有POST PUT 等等
http请求方法如下:
- GET 获取资源 (幂等)
- POST 新增资源
- HEAD 获取 HEAD 元数据 (幂等)
- PUT 更新资源 (带条件时幂等)
- DELETE 删除资源 (幂等)
- CONNECT 建立 Tunnel 隧道
- OPTIONS 获取服务器支持访问资源的方法 (幂等)
- TRACE 回显服务器收到的请求,可以定位问题。(有安全风险)
请求头是把浏览器的一些基础信息告诉服务器。比如包含了浏览器所使用的操作系统、浏览器内核等信息,以及当前请求的域名信息、浏览器端的 Cookie 信息等
请求体 如果是发送POST请求还需要通过请求体告诉服务器传输的具体内容
7. 服务器处理请求
浏览器发送请求到服务器之后服务器就可以对请求信息进行处理
8. 服务器响应请求
一旦服务器处理结束,便可以返回数据给浏览器了。服务器响应的数据格式如下图
首先服务器会返回响应行,包括协议版本和状态码。比如 200 表示请求成功,如果没有找到页面,则会返回404
详细状态码可查看:最全的HTTP响应状态码列表
服务器也会随同响应向浏览器发送响应头。响应头包含了服务器自身的一些信息,比如服务器生成返回数据的时间、返回的数据类型(JSON、HTML、流媒体等类型),以及服务器要在客户端保存的 Cookie 等信息
发送完响应头后,服务器就可以继续发送响应体的数据,通常,响应体就包含了 HTML 的实际内容
9. 断开连接
通常情况下,一旦服务器向客户端返回了请求数据,它就要关闭 TCP 连接。不过如果浏览器或者服务器在其头信息中加入了:Connection:Keep-Alive 那么 TCP 连接在发送后将仍然保持打开状态,这样浏览器就可以继续通过同一个 TCP 连接发送请求。保持 TCP 连接可以省去下次请求时需要建立连接的时间,提升资源加载速度。比如,一个 Web 页面中内嵌的图片就都来自同一个 Web 站点,如果初始化了一个持久连接,你就可以复用该连接,以请求其他资源,而不需要重新再建立新的 TCP 连接
断开TCP连接主要是通过四次挥手,可参考TCP/IP 是如何工作的中相关内容。
10. 特殊情况 重定向
响应行返回的状态码是 301,状态 301 就是告诉浏览器,我需要重定向到另外一个网址,而需要重定向的网址正是包含在响应头的 Location 字段中,接下来,浏览器获取 Location 字段中的地址,并使用该地址重新导航,这就是一个完整重定向的执行流程
相关问题
-
为什么很多站点第二次打开速度会很快? 很多网站第二次访问能够秒开,是因为这些网站把很多资源都缓存在了本地,浏览器缓存直接使用本地副本来回应请求,而不会产生真实的网络请求,从而节省了时间。同时,DNS 数据也被浏览器缓存了,这又省去了 DNS 查询环节 浏览器资源缓存的详细内容可参考:浏览器静态资源缓存机制(网络篇)
-
登录状态是如何保持的? 如果服务器端发送的响应头内有 Set-Cookie 的字段,那么浏览器就会将该字段的内容保持到本地。当下次客户端再往该服务器发送请求时,客户端会自动在请求头中加入 Cookie 值后再发送出去。服务器端发现客户端发送过来的 Cookie 后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录,最后得到该用户的状态信息