相关文章
一次完整的HTTP事务流程
(1)域名解析
(2)发起TCP的三次握手
(3)建立TCP连接后发起http请求
(4)服务器响应http请求,浏览器得到HTML代码
(5)浏览器解析HTML代码,并请求HTML代码中的资源
(6)浏览器对页面进行渲染呈现给用户
(7)连接结束
Tcp三次握手?四次挥手?
三次握手的必要性:为了保证服务器能接收到客户端的信息并做出正确的应答而进行前两次(第一次和第二次)握手,为了保证客户端能够接收到服务端的信息并能做出正确的应答而进行后两次(第二次和第三次)握手。
上图部分标志说明:
(1)ACK:TCP规定,只有当ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1
(2)SYN(SYNchronization):在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这个是一个连接请求报文。对方若同意建立连接,则响应报文中SYN=1,ACK=1。因此,SYN置1表示这是一个连接请求或连接接受报文。
(3)FIN(finish):终结的意思,用来释放一个连接。当FIN=1时,表明此报文段的发送方的数据已经发送完毕,并请求释放连接。
三次握手说明:
(1)第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置1,序列号seq(sequence number)为x;然后,客户端进入SYN_SEND状态,等待服务器的确认。
(2)第二次握手:服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,ACK位置1,确认号ack(acknowledgement number)为x+1;同时,自己还要发送SYN请求信息,将SYN位置1,序列号seq为y;服务器将上述SYN+ACK报文段一并发送给客户端,此时服务器进入SYN_RECV状态。
(3)第三次握手:客户端收到服务器的SYN+ACK报文段。然后将确认号ack设置为y+1,向服务器发送ACK报文段。这个报文段发送完毕后,客户端和服务器都进入ESTABLISHED状态,完成TCP三次握手,之后可以开始传数据。
四次挥手:当客户端和服务器通过三次握手建立了TCP连接之后,当数据传输完毕,就要断开TCP连接,这个过程称为四次挥手。四次挥手说明:
(1)第一次挥手:主机1(可以是客户端,也可以是服务器)设置序列号seq为u,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT状态,这表示主机1没有数据要发送给主机2了。
(2)第二次挥手:主机2收到了主机1发送的FIN报文段,向主机1回复一个ACK报文段,确认号ack为u+1,序列号seq为v;主机2进入CLOSE_WAIT状态;主机1收到主机2发送的ACK报文段之后,进入FIN_WAIT_2状态。
(3)第三次挥手:主机2向主机1发送FIN报文段,设置序列号seq为w,确认号ack为u+1,请求关闭连接,同时主机2进入LAST_ACK状态
(4)第四次挥手:主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,确认号ack为w+1,序列号seq为u+1,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL(MSL,最长报文段寿命)后依然没有收到回复,则证明服务端已经正常关闭,那么主机1也可以关闭连接了。
HTTP请求码及其作用?
HTTP状态码:当用户访问一个网页时,浏览器会向网页所在的服务器出请求,当浏览器接收并显示网页前,此网页所在服务器会返回一个包含HTTP状态码的信息头(server header)用以响应浏览器的请求,HTTP状态码用于描述服务器对请求的处理结果。
HTTP状态码分类:
(1)1**:信息,服务器收到请求,需要请求者继续执行操作
(2)2**:成功,操作被成功接收并处理
(3)3**:重定向,需要进一步的操作以完成请求
(4)4**:客户端错误,请求包含语法错误或者无法完成请求
(5)5**:服务器错误,服务器在处理请求的过程中发生了错误
常见的HTTP状态码:
- 200——OK,请求成功
- 301——Moved Permanently,资源(网页等)被永久转移到其他URL
- 302——Found,307——Temporary Redirect,临时重定向,请求的文档被临时移动到别处
- 304——Not Modified,未修改,表示客户端缓存的版本是最近的 💛
- 401——Unauthorized,请求要求用户的身份认证
- 403——Forbidden,禁止,服务器理解客户端请求,但是拒绝处理此请求,通常是权限设置所致
- 404——Not Found,请求的资源(网页等)不存在
- 500——Internal Server Error——内部服务器错误
- 502——Bad Gateway,充当网关或代理的服务器从远端服务器接收到了一个无效的请求
- 504——Gateway Time-out,充当网关或代理的服务器,未及时从远端服务器获取请求
浏览器解析渲染过程?
(1)浏览器解析HTML源码,然后创建一个DOM树。
在DOM树中,每一个HTML标签都有一个对应的节点(元素节点),并且每一个文本也都有一个对应的文本节点,DOM树的根节点就是documentElement,对应的是html标签
(2)浏览器解析CSS代码,然后创建一个CSSOM树。
解析CSS的时候会按照如下顺序来定义优先级(递增):浏览器默认设置<用户设置<外联样式<内联样式<标签样式
(3)根据DOM树和CSSOM来构建一个渲染树(render tree)。
(4)当渲染树创建完成之后,浏览器就可以根据渲染树直接把页面绘制到屏幕上。
渲染树(render tree)和DOM树的关系?
(1)在DOM树构建的同时,浏览器会构建渲染树。(为了提高用户体验,浏览器并不会等到所有HTML文档加载完成之后才建立渲染树并渲染,而是会在从网络层获取html文档的同时把已经接收到的局部内容先渲染出来)
(2)DOM树完全和html标签一一对应,而渲染树会忽略(即不包含)不需要渲染的元素(如head,样式为display:none的元素等)
(3)渲染树中每一个节点都存储着对应的CSS属性
reflow(重排,回流)和repaint(重绘)?
reflow:浏览器要花时间去渲染,当它发现了某个部分发生了变化并且影响了布局,就需要倒回去重新渲染
repaint:如果只是改变了某个元素的背景颜色或文字颜色等,不影响元素周围或内部布局,就只会引起浏览器的repaint,重画其中一部分。
reflow比repaint更花费时间,也就更影响性能,所以在写代码时应尽量避免过多的reflow。
什么时候会发生reflow?
(1)页面初始化的时候
(2)操作DOM的时候(增加或删除DOM元素)
(3)某些元素的尺寸改了(边距,填充,边框,宽高)
(4)CSS的属性发生变化(隐藏display:none)
(5)内容改变(文本改变或图片改变而引起的的计算值的宽高改变)
(6)浏览器窗口尺寸改变(当resize事件发生时)
如何减少reflow/repaint?
(1)不要逐个修改DOM样式,可以预先定义好css的class,然后修改DOM的className,将多个需要进行相同操作的元素一次修改
(2)不要把DOM结点的属性值放在一个循环里当成循环的变量
(3)当动画元素使用fixed或absolute的position时(脱离了文档流),那么在修改他们的CSS时不会发生reflow
(4)不要使用table布局,因为可能很小的一个改动都会造成整个table的重新布局
(5)在内存中多次操作结点,完成后再添加到文档中去
(6)如果要对一个元素进行复杂的操作,可以先隐藏它(display:none),操作完成后再显示
(7)对于需要经常取出的引起浏览器重排的属性值,要缓存到变量中
为什么要先引入css文件,再引入js文件?
(1)js代码的下载是阻塞下载,不可以和其他代码并行下载和解析;CSS的加载不会阻塞DOM树的解析(会阻塞其渲染,也会阻塞后面的js执行)
(2)页面加载时,是按照从上到下,从左到右的顺序加载的。如果将js放在前面,会立即执行,阻塞后续的资源下载和执行。如果外部脚本加载时间过长,会造成网页长时间失去响应,浏览器就会呈现“假死”状态(阻塞效应)
(2)页面需要等到head中的js和css加载完成之后才开始绘制,当js放在body最后时,不需要等待,可以避免资源阻塞,同时使静态页面迅速显示
(3)部分js的执行依赖于前面的样式。
(4)js一般是处理功能,所以不需要提前加载。先给用户观感,在给用户上手体验。
HTTP和HTTPS的区别
HTTP(Hyper Text Transfer Protocol,超文本传输协议)被用于在web浏览器和网站服务器之间传递信息,HTTP协议以明文的方式发送内容,不提供任何方式的数据加密,如果攻击者截取了web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此,HTTP协议不适合传输一些敏感信息,比如:信用卡号,密码等支付信息。
HTTPS(Hyper Text Transfer Protocol over Secure Socket Layer,安全套接字超文本传输协议),为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL/TLS,依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。其中SSL(Secure Socket Layer,安全套接层),TLS(Transport Layer Securit,传输层安全协议),SSL 3.0和TLS 1.0差别很小,在HTTPS通信中具体使用哪一个还要看客户端和服务端的支持程度,二者在网络模型中位于哪一层?
区别:
(1)HTTPS协议需要CA申请证书,一般免费证书比较少,所以需要一定费用
(2)HTTP是超文本传输协议,信息室明文传输,HTTPS则是具有安全性的SSL加密传输协议
(3)HTTP和HTTPS使用的是完全不同的连接方式,使用的端口号也不一样,前者是80,后者是443
(4)HTTP连接很简单,是无状态的;HTTPS协议是由HTTP+SSL协议构建的可进行加密传输、身份认证的网络协议,比较安全。
(5)谷歌搜索引擎算法中,比起同等HTTP网站,采用HTTPS加密的网站在搜索结果中排名会更高
客户端使用HTTPS方式与web服务器通信的步骤:
(1)客户使用HTTPS的URL访问web服务器,要求与web服务器建立SSL连接
(2)web服务器收到客户端请求后,将网站的证书信息(证书中包含公钥)传送一份给客户端
(3)客户端的浏览器与web服务器开始协商SSL连接的安全等级,也就是信息的加密等级
(4)客户端的浏览器根据双方同意的安全等级,建立会话秘钥,然后利用网站的公钥将会话秘钥加密,并传送给网站
(5)web服务器利用自己的私钥解密出会话秘钥
(6)web服务器利用会话秘钥加密与客户端之间的通信
浏览器同源策略
(1)浏览器安全的基石是“同源策略”(same-origin policy)。所谓“同源”指的是“三个相同”:
- 协议相同
- 域名相同
- 端口相同
(2)同源策略的目的是为了保证用户信息的安全,防止恶意的网站窃取数据。不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源。
(3)如果非同源,共有三种行为受到限制:
- Cookie、LocalStorage和IndexDB无法读取
- DOM无法获得
- AJAX请求不能发送
(4)不受同源策略限制的:
- 页面中的链接,重定向以及表单提交
- 跨域资源的引入是可以的,但是js不能读写加载的内容。(如,,,)
长链接和短链接
短链接
完成一次通信之后,客户端主动断开TCP连接;
HTTP/1.0
中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次HTTP
操作,就建立一次连接(三次握手),结束就中断(四次挥手);
长链接
完成一次通信之后,客户端不主动断开 TCP
连接,而是复用该TCP
连接;
HTTP/1.1
起,默认使用长连接,用以保持连接特性。此时通用首部字段中的Connection
字段值为:Keep-Alive
;
长连接适用于频繁地传输数据的客户端和服务器,为了防止过多的TCP连接影响服务器性能,需要对长时间不用的连接进行释放;
缓存工作方式(强缓存和协商缓存)
- 场景一:
让服务器与浏览器约定一个文件过期时间————Expires
,在Expires
没有过期的情况下,客户端发出请求时,直接使用HTTP本地缓存并返回200,这种方式称为强制缓存
- 场景二:
让服务器在与浏览器在约定文件过期时间Expires
的基础上,再加一个文件最新修改时间的对比————Last-Modified
与If-Modified-Since
- 情况1:如果
Expires
没有过期,直接采用强制缓存 情况2:如果
Expires
过期了,那么浏览器在请求服务器的时候,就带上了文件最新修改时间,这个字段是在请求头上面加了Is-Modified-Since
字段,其实该字段的值就是上次请求时服务器返回的Last-Modified
值;服务器会把请求头里的If-Last-Modified
的值与服务器上的文件最新修改时间Last-Modified
的值进行比较- 如果
If-Modified-Since
不等于Last-Modified
,说明浏览器缓存的资源(f.js
)发生改变,服务器就会去查找最新的f.js
,同时再次返回Expires
、f.js
、Last-Modified
,返回的状态码为200
; - 如果
If-Modified-Since
等于Last-Modified
,说明浏览器缓存的资源(f.js
)没有发生改变,浏览器可以继续使用HTTP
本地缓存,此时服务器返回状态码304
;这种方式称为协商缓存
- 如果
- 场景三:
让服务器在过期时间Expires
+Last-Modified
的基础上,增加一个文件唯一标识Etag
与If-None-Match
配成一对使用;除此之外,Expires
不稳定,再加入一个Max-age
来加以替代(Max-age
优先级更高)
- 在60s内,浏览器不再向服务器发起请求,直接使用本地缓存这与
Expires
相似。 60s后:浏览器带上
If-Modified-Since
和If-None-Match
(也就是上次服务器返回的Etag
值)发起请求,服务器会对比If-None-Match
与服务器端的Etag
值,这时即使浏览器也提供了If-Modified-Since
也不会再与Last-Modified
进行对比,因为Etag
的优先级比Last-Modified
高(更精准);- 如果
If-None-Match
不等于Etag
,说明f.js
文件已被修改,服务器就会返回最新的f.js
和全新的Etag
与Max-age
(比如60
),当然也会顺便把Expires
与Last-Modified
返回(尽管没用);返回的状态码为200
; - 如果
If-None-Match
等于Etag
,说明f.js
文件没有被修改,这时服务器返回的状态码为304
,告诉浏览器继续使用原来的本地缓存。这种方式属于协商缓存;
- 如果
有了Last-Modified为什么还要用Etag呢?
你可能会觉得使用Last-Modified
已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag
呢?HTTP1.1
中Etag
的出现主要是为了解决几个Last-Modified
比较难解决的问题:
- 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新
GET
; - 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说
1s
内修改了N
次),If-Modified-Since
能检查到的粒度是s
级的,这种修改无法判断(比如淘宝每ms
都会更新数据); - 某些服务器不能精确的得到文件的最后修改时间;
这时,利用Etag
能够更加准确的控制缓存,因为Etag
是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符。 Last-Modified
与ETag
是可以一起使用的,服务器会优先验证ETag
,一致的情况下,才会继续比对Last-Modified
,最后才决定是否返回304
。
强制缓存和协商缓存区别
- 强制缓存:直接使用
http
本地缓存,此时服务器返回状态码时200 - 协商缓存:向服务器确认
http
本地缓存的资源是否发生变化,没变化后再使用http
本地缓存,此时服务器返回状态时304;资源发生变化直接返回最新资源,状态码为200;可以这样理解凡是304状态码,都属于协商缓存
请求头Cache-control
的值为no-cache时表示浏览器会向服务器确认缓存的新鲜度,再决定是否使用缓存,属于协商缓存
浏览器操作对缓存的影响
用户操作 | Expires/Cache-Control | Last-Modified/Etag |
---|---|---|
地址栏回车 | 有效 | 有效 |
页面链接跳转 | 有效 | 有效 |
新开窗口 | 有效 | 有效 |
前进、后退 | 有效 | 有效 |
F5刷新 | 无效 | 有效 |
Ctrl + F5刷新 | 无效 | 无效 |
关于http中的keep-alive
在http早期,每一个http请求都要打开一个tcp socket 连接,并且使用一次后就会断开连接。使用keep-alive可以改善这种状态,减少tcp请求次数,减少TIME_WAIT状态连接,以此提高性能和httpd服务器的吞吐率,但是keep-alive并不代表可以永久使用,长时间容易导致系统资源w无效占用,比重复利用连接带来的损失还要大,所以要正确设置keep-alive的时间。