HTTP协议,正是建⽴在TCP连接基础之上的。HTTP是⼀种允许浏览器向服务器获取资源的协议,是 Web的基础
HTTP也是浏览器使⽤最⼴的协议
输入一个url会发生什么?
构建请求
⾸先,浏览器构建请求⾏信息,如下
GET /index.html HTTP1.1
查找缓存
在真正发起⽹络请求之前,浏览器会先在浏览器缓存中查询是否有要请求的⽂件。其中,浏览器缓存是⼀种 在本地保存资源副本,以供下次请求时直接使⽤的技术。
当浏览器发现请求的资源已经在浏览器缓存中存有副本,它会拦截请求,返回该资源的副本。这样做的好处有:
- 缓解服务器端压⼒,提升性能(获取资源的耗时更短了);
- 对于⽹站来说,缓存是实现快速资源加载的重要组成部分。
当然,如果缓存查找失败,就会进⼊⽹络请求过程了。
准备IP地址和端⼝
HTTP和TCP的关系
浏览器使⽤HTTP协议作为 应⽤层协议,⽤来封装请求的⽂本信息;并使⽤TCP/IP作传输层协议将它发到⽹络上
在HTTP⼯作开 始之前,浏览器需要通过TCP与服务器建⽴连接。也就是说HTTP的内容是通过TCP的传输数据阶段来实现的
-
HTTP⽹络请求的第⼀步是做什么呢?
是和服务器建⽴TCP连接
-
那怎么获取IP地址和端⼝号呢?
利⽤URL 地址来获取IP和端⼝信息
IP是 难以记忆,
负责把域名和IP地址做⼀⼀映射关系。这套域名映射为IP的系统就叫 做“域名系统”,简称DNS
在第⼀步浏览器会请求DNS返回域名对应的IP,当然浏览器还提供了 DNS数据缓存服务。
如果某个域名已经解析过了,那么浏览器会缓存解析的结果,以供下次查询时直接使 ⽤,这样也会减少⼀次⽹络请求。
拿到IP之后,接下来就需要获取端⼝号了。通常情况下,如果URL没有特别指明端⼝号,那么HTTP协议默认是80端⼝。
等待TCP队列
现在已经把端⼝和IP地址都准备好了,那么下⼀步是不是可以建⽴TCP连接了呢?
答案依然是“不⾏”。Chrome有个机制,同⼀个域名同时最多只能建⽴6个TCP连接,如果在同⼀个域名下同时有10个请求发⽣,那么其中4个请求会进⼊排队等待状态,直⾄进⾏中的请求完成。
当然,如果当前请求数量少于6,会直接进⼊下⼀步,建⽴TCP连接。
建⽴TCP连接
排队等待结束之后,终于可以快乐地和服务器握⼿了。
发送HTTP请求
⼀旦建⽴了TCP连接,浏览器就可以和服务器进⾏通信了。⽽HTTP中的数据正是在这个通信过程中传输 的。
⾸先浏览器会向服务器发送请求⾏,它包括了请求⽅法、请求URI(Uniform Resource Identifier)和 HTTP版本协议。
在浏览器发送请求⾏命令之后,还要以请求头形式发送其他⼀些信息,⽐如包含了浏览器所使⽤的操作系统、浏览器内核等信息,以及当前请求的域名信息、浏览器端的 Cookie信息,等等。
服务端处理HTTP请求流程
历经千⾟万苦,HTTP的请求信息终于被送达了服务器。接下来,服务器会根据浏览器的请求信息来准备相 应的内容。
返回请求
⼀旦服务器处理结束,便可以返回数据给浏览器了。
返回响应⾏、响应头和响应体的数据
⾸先服务器会返回响应⾏,包括协议版本和状态码。
服务器会 通过请求⾏的状态码来告诉浏览器它的处理结果
服务器也会随同响应向浏览器发送响应头。
发送完响应头后,服务器就可以继续发送响应体的数据
断开连接
⼀旦服务器向客⼾端返回了请求数据,它就要关闭 TCP 连接。不过如果浏览器或者服务器在 其头信息中加⼊了:Connection:Keep-Alive
那么TCP连接在发送后将仍然保持打开状态,这样浏览器就可以继续通过同⼀个TCP连接发送请求。保持 TCP连接可以省去下次请求时需要建⽴连接的时间,提升资源加载速度。
重定向
⽐如当你在浏览器中打开geekbang.org 后,你会发现最终打开的⻚⾯地址是 https://www.geekbang.org。
这两个URL之所以不⼀样,是因为涉及到了⼀个重定向操作。
状态301就是告诉浏览器,我需要重定向到另外⼀个⽹ 址,⽽需要重定向的⽹址正是包含在响应头的Location字段中,接下来,浏览器获取Location字段中的地 址,并使⽤该地址重新导航,这就是⼀个完整重定向的执⾏流程
所以为什么很多站点第⼆次打开速度会很快?
DNS缓存和⻚⾯资源缓存这两块数据是 会被浏览器缓存的。
DNS缓存⽐较简单,它主要就是在浏览器本地把对应的IP和域名关联起来
重点看下浏览器资源缓存
当服务器返回HTTP响应头给浏览器时,浏览器是通过响应头中的Cache-Control字段来设置是否缓存该资源。
通过Cache-Control中的Max-age参数来设置缓存过期时间
但如果缓存过期了,浏览器则会继续发起⽹络请求,并且在HTTP请求头中带上:If-None-Match:"4f80f-13c-3a1xb12a"
服务器收到请求头后,会根据If-None-Match的值来判断请求的资源是否有更新。
- 如果没有更新,就返回304状态码,相当于服务器告诉浏览器:“这个缓存可以继续使⽤,这次就不重复 发送数据给你了。”
- 如果资源有更新,服务器就直接返回最新资源给浏览器。
登录状态是如何保持的?
-
⽤⼾打开登录⻚⾯,在登录框⾥填⼊⽤⼾名和密码,点击确定按钮
-
服务器接收到浏览器提交的信息校验之后,会⽣成⼀ 段表⽰⽤⼾⾝份的字符串,并把该字符串写到响应头的Set-Cookie字段⾥,如下所⽰,然后把响应头发送 给浏览器。
Set-Cookie: UID=3431uad;
-
浏览器在接收到服务器的响应头后,开始解析响应头,如果遇到响应头⾥含有Set-Cookie字段的情况,浏 览器就会把这个字段信息保存到本地。⽐如把UID=3431uad保持到本地。
-
当⽤⼾再次访问时,浏览器会发起HTTP请求,但在发起请求之前,浏览器会读取之前保存的Cookie数 据,并把数据写进请求头⾥的Cookie字段⾥(如下所⽰),然后浏览器再将请求头发送给服务器。
-
服务器在收到HTTP请求头数据之后,就会查找请求头⾥⾯的“Cookie”字段信息,当查找到包 含UID=3431uad的信息时,服务器查询后台,并判断该⽤⼾是已登录状态,然后⽣成含有该⽤⼾信息的 ⻚⾯数据,并把⽣成的数据发送给浏览器。
-
浏览器在接收到该含有当前⽤⼾的⻚⾯数据后,就可以正确展⽰⽤⼾登录的状态信息了