这是我参与8月更文挑战的第31天,活动详情查看: 8月更文挑战
浏览器发送请求,是否需要查看缓存?如何检查?服务器接受到请求,是否需要检查缓存?检查什么字段?http1.0和http1.1缓存区别?
浏览器发送请求,需要经历强缓存过程,首先本地是否已有了该请求资源的缓存
没有,直接发送请求获取资源
有缓存,判断是否过期
未过期,返回状态码为200,直接从本地读取缓存
过期,发送请求,验证资源是否命中协商缓存
命中协商缓存,将请求返回,但是不会返回这个资源的数据
未命中,从服务器加载资源返回数据
强缓存过程由浏览器单独完成,协商缓存需要服务器参与
强缓存过程:
根据请求头的Expires 和 Cache-control 判断是否命中强缓存,检查缓存是否过期,如何检查强缓存是否过期
查看Cache-Control是否有的s-maxage或max-age指令,若有,则使用响应报文的生成时间获得过期时间,再与当前时间进行对比
如果没有Cache-Control的s-maxage或max-age指令,则比较Expires中的过期时间与当前时间。Expires是一个绝对时间。
另外下面列几个Cache-Control的常用指令:
no-cache:含义是不使用本地缓存,需要使用协商缓存,也就是先与服务器确认缓存是否可用。
no-store:禁用缓存。
public:表明其他用户也可使用缓存,适用于公共缓存服务器的情况。
private:表明只有特定用户才能使用缓存,适用于公共缓存服务器的情况。
协商缓存过程:
判断缓存中是否有ETag或Last-Modified字段,没有,则发起一个http请求,服务器根据请求返回资源,在返回的 respone 的 header 加入ETag字段(标识字符串),Last-Modified(资源的最后修改时间)
如果有这两个字段,则在请求头中添加If-None-Match字段(有ETag字段的话添加,值就是上次响应报文中的ETag的值)、If-Modified-Since字段(有Last-Modified字段的话添加,值就是上一次请求返回的 Last-Modified 值)
服务器根据请求传过来的值判断资源是否有变化,没有则返回 304,有变化就正常返回资源内容,更新 Last-Modified 的值
304 则从缓存加载资源,否则直接从服务器加载资源
注意:
如果同时发送If-None-Match 、If-Modified-Since字段,服务器只要比较If-None-Match和ETag的内容是否一致即可;如果内容一致,服务器认为缓存仍然可用,则返回状态码304。
当ETag命中时,ETag会仍旧在响应头中返回,即使它没有变化,但如果Last-Modified命中时,响应头中不会再添加Last-Modified字段,也就是说Last-Modified的过期时间,永远是根据第一次返回时的值确定的
http1.0和http1.1缓存相关了解
在HTTP/1.1中,引入了Cache-Control,当首部字段Cache-Control有指定s-maxage或max-age指令,比起http1.0的Expires,优先处理s-maxage或max-age。其中Cache-Control:max-age定义了文档的使用期,是一个相对时间,Expires指定的是一个绝对时间。
同样ETag也是http1.1引入的,ETag能够更加准确的控制缓存,因为ETag是服务器自动生成的资源在服务器端的唯一标识符,资源每次变动,都会生成新的ETag值。Last-Modified与ETag是可以一起使用的,但服务器会优先验证ETag。
DNS获取ip过程?
首先查找的是浏览器的DNS缓存,浏览器会缓存DNS记录一段时间。所以浏览器会先去查自己的缓存,要是域名在缓存中有记录则使用缓存中的IP进行下一步处理。要是没有则进行下一步查找。
查询系统缓存。如果浏览器缓存中没有,浏览器会去查找系统中记录的DNS信息。首先检查域名是否在本地 hosts 里,再查系统本地缓存的其他DNS 记录。hosts是一个没有扩展名的系统文件,其基本作用就是将一些常用的网址域名与其对应的 IP 地址建立一个关联“ 数据库 ”。(例如我们访问测试环境,配置的host)
路由器缓存。如果在系统缓存里面还是没找到对应的IP,那么接着会发送一个请求到路由器上,然后路由器在自己的路由器缓存上查找记录,路由器一般也存有DNS信息(缓存你上过的网站,所以有时路由器需要进行DNS刷新)
ISP DNS缓存。如果本地路由器还是没有,这个请求就会被发送到ISP(注:Internet Service Provider,互联网服务提供商,所谓的电信网,联通网和移动网),ISP也会有相应的ISP DNS服务器。
递归DNS查询。如果在ISP DNS服务器还没有查到的话,那么就要进行DNS递归查询了。假设我需要www.baidu.com的IP
向客户端主机向本地域名服务器查询,www.baidu.com在本地域名服务器上找不到
这时候本地域名服务器就会到根域名服务器查找,根域名服务器说这个是一个.com域名,然后返回顶级域名服务器的IP地址
然后本地域名服务器就跑到管理.com域名的顶级域名服务器上进行进一步查询,顶级域名服务器说是 .baidu二级域名。然后返回权威DNS服务器的IP地址
最后本地域名服务器再跑到管理 .baidu这个二级域名所在的权限域名服务器,去查询 www这个三级域名的ip 地址。然后ip地址给本地域名服务器
最后本地域名服务器将地址返回给客户端主机
这里的查询过程是包含递归查询和迭代查询的,客户端主机发送给本地服务器的查询是递归查询,而后面的三个查询是迭代查询。
建立 TCP 链接的三次握手
第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认;(SYN同步序列编号)
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
关闭 TCP 的四次挥手是什么?
先由客户端向服务器端发送一个FIN,请求关闭数据传输。客户端进FIN_WAIT_1状态
当服务器接收到客户端的FIN时,向客户端发送一个ACK,其中ack的值等于FIN+SEQ。服务端进入CLOSE_WAIT状态。
然后服务器向客户端发送一个FIN,告诉客户端应用程序关闭。服务端进入LAST_ACK状态
当客户端收到服务器端的FIN是,回复一个ACK给服务器端。客户端进入TIME_WAIT状态,服务端收到,进入CLOSED状态
由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭
为什么要4次挥手,是因为要确保数据能够完整传输。
当被动方收到主动方的FIN报文通知时,它仅仅表示主动方没有数据再发送给被动方了。
但未必被动方所有的数据都完整的发送给了主动方,所以被动方不会马上关闭SOCKET,它可能还需要发送一些数据给主动方后,
再发送FIN报文给主动方,告诉主动方同意关闭连接,所以这里的ACK报文和FIN报文多数情况下都是分开发送的。