输入url后,首先需要找到这个url域名的服务器ip,为了寻找这个ip,浏览器首先会寻找缓存,查看缓存中是否有记录,缓存的查找记录为:浏览器缓存-》系统缓存-》路由器缓存,缓存中没有则查找系统的hosts文件中是否有记录,如果没有则查询DNS服务器,得到服务器的ip地址后,浏览器根据这个ip以及相应的端口号,构造一个http请求,这个请求报文会包括这次请求的信息,主要是请求方法,请求说明和请求附带的数据,并将这个http请求封装在一个tcp包中,这个tcp包会依次经过传输层,网络层,数据链路层,物理层到达服务器,服务器解析这个请求来作出响应,返回相应的html给浏览器,因为html是一个树形结构,浏览器根据这个html来构建DOM树,在dom树的构建过程中如果遇到JS脚本和外部JS连接,则会停止构建DOM树来执行和下载相应的代码,这会造成阻塞,这就是为什么推荐JS代码应该放在html代码的后面,之后根据外部央视,内部央视,内联样式构建一个CSS对象模型树CSSOM树,构建完成后和DOM树合并为渲染树,这里主要做的是排除非视觉节点,比如script,meta标签和排除display为none的节点,之后进行布局,布局主要是确定各个元素的位置和尺寸,之后是渲染页面,因为html文件中会含有图片,视频,音频等资源,在解析DOM的过程中,遇到这些都会进行并行下载,浏览器对每个域的并行下载数量有一定的限制,一般是4-6个,当然在这些所有的请求中我们还需要关注的就是缓存,缓存一般通过Cache-Control、Last-Modify、Expires等首部字段控制。 Cache-Control和Expires的区别在于Cache-Control使用相对时间,Expires使用的是基于服务器 端的绝对时间,因为存在时差问题,一般采用Cache-Control,在请求这些有设置了缓存的数据时,会先 查看是否过期,如果没有过期则直接使用本地缓存,过期则请求并在服务器校验文件是否修改,如果上一次 响应设置了ETag值会在这次请求的时候作为If-None-Match的值交给服务器校验,如果一致,继续校验 Last-Modified,没有设置ETag则直接验证Last-Modified,再决定是否返回304
输入完网址按下回车,到看到网页这个过程中发生了什么
1.浏览器向DNS服务器请求解析该 URL 中的域名所对应的 IP 地址;
2.跟服务器建立TCP连接(三次握手);
3.建立TCP连接后浏览器发出HTTP 请求
4.服务器对浏览器请求作出响应,并把对应的 html 代码发送给浏览器;
5.浏览器解析HTML代码,并请求HTML代码中资源(如js,css,图片)
6.浏览器对页面进行渲染并呈现给用户;
7.服务器关闭TCP连接(四次挥手)
a.域名解析
DNS域名系统,是应用层协议,运行UDP协议之上,使用端口43。
浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有该请求资源,会直接在屏幕中显示页面内容,没有再使用DNS服务器解析,本地查询是递归查询,依次通过浏览器缓存 —>> 本地hosts文件 —>> 本地DNS解析器 —>>本地DNS服务器 —>> 其他域名服务器请求。接下来的过程就是迭代过程。
递归查询一般而言,发送一次请求就够,迭代过程需要用户发送多次请求。
DNS 使用 UDP 协议作为传输层协议的主要原因是为了避免使用 TCP 协议时造成的连接时延。
为了得到一个域名的 IP 地址,往往会向多个域名服务器查询,如果使用 TCP 协议,那么每次请求都会存在连接时延,这样使 DNS 服务变得很慢。
大多数的地址查询请求,都是浏览器请求页面时发出的,这样会造成网页的等待时间过长。
浏览器会判断所请求的资源是否在缓存里,如果请求的资源在缓存里并且没有失效,那么就直接使用,否则向服务器发起新的请求。
b. 发起TCP的3次握手
TCP协议采用了三次握手策略。发送端首先发送一个带SYN(synchronize)标志的数据包给接收方,接收方收到后,回传一个带有SYN/ACK(acknowledegment)标志的数据包以示传达确认信息。最后发送方再回传一个带ACK标志的数据包,代表握手结束。
为什么要第三次挥手?避免服务器等待造成资源浪费
c. 建立TCP连接后发起http请求
HTTP1.0定义了三种请求方法,GET,POST和HEAD方法 HTTP1.1新增六种请求方法:OPTIONS,PUT,PATCH,DELETE,TRACH和CONNECT
请求方法:
GET:获取资源
POST:传输资源
PUT:更新资源
DELETE:删除资源
HEAD:获得报文首部
OPTIONS:返回支持的请求方法
TRACE:追踪路径
HTTP报文的组成部分
http报文包括:请求报文和响应报文。
(1)请求行:包含http方法,页面地址,http协议,版本。
(2)请求头:key,value值,告诉服务端我要哪些内容。
(3)空行:分隔请求头、请求体。
(4)请求体:数据部分。
状态行:http协议及版本、状态码及状态描述。
GET 用于获取资源,POST 用于提交资源。
d. 服务器端响应http请求,浏览器得到html代码
服务器在收到浏览器发送的HTTP请求之后,会将收到的HTTP报文封装成HTTP的Request对象,并通过不同的Web服务器进行处理,处理完的结果以HTTP的Response对象返回,主要包括状态码,响应头,响应报文三个部分。
1xx 信息类
接受的请求正在处理,信息类状态码。
2xx 成功
200 OK 表示从客户端发来的请求在服务器端被正确请求。
204 No content,表示请求成功,但没有资源可返回。
206 Partial Content,该状态码表示客户端进行了范围请求,而服务器成功执行了这部分的 GET 请求响应报文中包含由 Content-Range 指定范围的实体内容。
3xx 重定向
301 moved permanently,永久性重定向,表示资源已被分配了新的 URL,这时应该按 Location 首部字段提示的 URI 重新保存。
302 found,临时性重定向,表示资源临时被分配了新的 URL。
303 see other,表示资源存在着另一个 URL,应使用 GET 方法获取资源。
304 not modified,当协商缓存命中时会返回这个状态码。
307 temporary redirect,临时重定向,和302含义相同,不会改变method
当 301、302、303 响应状态码返回时,几乎所有的浏览器都会把 POST 改成 GET,并删除请求报文内的主体,之后请求会自动再次发送301、302 标准是禁止将 POST 方法改变成 GET 方法的,但实际使用时大家都会这么做
4XX 客户端错误
400 bad request,请求报文存在语法错误。
401 unauthorized,表示发送的请求需要有通过 HTTP 认证的认证信息。
403 forbidden,表示对请求资源的访问被服务器拒绝。
404 not found,表示在服务器上没有找到请求的资源。
405 Method Not Allowed,服务器禁止使用该方法,客户端可以通过options方法来查看服务器允许的访问方法,如下
Access-Control-Allow-Methods →GET,HEAD,PUT,PATCH,POST,DELETE
5XX 服务器错误
500 internal sever error,表示服务器端在执行请求时发生了错误。
502 Bad Gateway,服务器自身是正常的,访问的时候出了问题,具体啥错误我们不知道。
503 service unavailable,表明服务器暂时处于超负载或正在停机维护,无法处理请求。
接下来,我们数据拿到了,你认为就会断开TCP连接吗?
这个的看响应头中的Connection字段。上面的字段值为close,那么就会断开,一般情况下,HTTP1.1版本的话,通常请求头会包含「Connection: Keep-Alive」表示建立了持久连接,这样TCP连接会一直保持,之后请求统一站点的资源会复用这个连接。
上面的情况就会断开TCP连接,请求-响应流程结束。
到这里的话,网络请求就告一段落了,接下来的内容就是渲染流程了
浏览器渲染原理:
当我们在浏览器地址输入URL时,浏览器会发送请求到服务器,服务器将请求的HTML文档发送回浏览器,浏览器将文档下载下来后,便开始从上到下解析,解析完成之后,会生成DOM。如果页面中有css,会根据css的内容形成CSSOM,然后DOM和CSSOM会生成一个渲染树,最后浏览器会根据渲染树的内容计算出各个节点在页面中的确切大小和位置,并将其绘制在浏览器上。
css文件的加载是与DOM的加载并行的,也就是说,css在加载时Dom还在继续加载构建,而过程中遇到的css样式或者img,则会向服务器发送一个请求,待资源返回后,将其添加到dom中的相对应位置中;
由于js文件不会与DOM并行加载,因此需要等待js整个文件加载完之后才能继续DOM的加载
解决方法:
前提,js是外部脚本;
标签时,渲染进程会停止解析 HTML,而去加载,解析和执行 JS 代码,停止解析 html 的原因在于 JS 可能会改变 DOM 的结构(使用诸如 documwnt.write()等API),等JavaScript引擎运行完毕,浏览器再从中断的地方恢复DOM构建。也就是说,如果你想首屏渲染的越快,就越不应该在首屏就加载 JS 文件,这也是都建议将 script 标签放在 body 标签底部的原因。当然在当下,并不是说 script 标签必须放在底部,因为你可以给 script 标签添加 defer 或者 async 属性。如果在 标签上添加了 async 或 defer 等属性,浏览器会异步的加载和执行JS代码,而不会阻塞渲染
优化方案:
移除js和css的文件下载:移除内联 JavaScript、内联 CSS;
尽量减少文件大小:如通过 webpack 等工具移除不必要的注释,并压缩 js 文件;
将不进行DOM操作或CSS样式修改的 JavaScript 标记上 async 或者 defer异步引入;
defer和async的区别
async:在加载完之后立即执行。也就是说它的执行仍然会阻塞文档的解析,只是它的加载过程不会阻塞。多个脚本的执行顺序 和加载顺序无关。
defer:表示延迟执行引入的 JavaScript,即这段 JavaScript 加载时 HTML 并未停止解析,这两个过程是并行的。在HTML解析完之后才会执行,DOMContentLoaded 事件触发之前完成。多个脚本则按照加载的顺序依次执行。
构建渲染树(Render Tree)
样式计算 主进程还会基于 CSS 选择器解析 CSS 获取每一个节点的最终的计算样式值。即使不提供任何 CSS,浏览器对每个元素也会有一个默认的样式。
获取布局 根据渲染树来布局,计算每个节点的位置
绘制各元素 即使知道了不同元素的位置及样式信息,我们还需要知道不同元素的绘制先后顺序才能正确绘制出整个页面。在绘制阶段,主线程会遍历布局树以创建绘制记录。绘制记录可以看做是记录各元素绘制先后顺序的笔记。
合成帧
连接结束(四次挥手)
通过四次挥手关闭连接
第一次挥手是浏览器发完数据后,发送FIN请求断开连接。
第二次挥手是服务器发送ACK表示同意。
第三次挥手是服务器发送FIN请求断开连接。(考虑到服务器可能还有数据要发送)
第四次挥手是浏览器需要返回ACK表示同意
为什么要四次挥手?由于服务器不能马上断开连接,导致FIN释放连接报文与ACK确认接收报文需要分两次传输,即第二次和第三次"挥手";
HTTP协议的主要特点
灵活可扩展。一个是语法上只规定了基本格式,空格分隔单词,换行分隔字段等。另外一个就是传输形式上不仅可以传输文本,还可以传输图片,视频等任意数据。
请求-应答模式,通常而言,就是一方发送消息,另外一方要接受消息,或者是做出相应等。
可靠传输,HTTP是基于TCP/IP,因此把这一特性继承了下来。
无状态,连接一次就会断开
首部行
首部可以分为四种首部,请求首部、响应首部、通用首部和实体首部。通用首部和实体首部在请求报文和响应报文中都可以设 置,区别在于请求首部和响应首部。
介绍一下Connection:keep-alive
什么是keep-alive
我们知道HTTP协议采用“请求-应答”模式,当使用普通模式,即非KeepAlive模式时,每个请求/应答客户和服务器都要新建一个连接,完成 之后立即断开连接(HTTP协议为无连接的协议);
当使用Keep-Alive模式(又称持久连接、连接重用)时,Keep-Alive功能使客户端到服 务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接。
为什么要使用keep-alive
keep-alive技术的创建目的,能在多次HTTP之前重用同一个TCP连接,从而减少创建/关闭多个 TCP 连接的开销(包括响应时间、CPU 资源、减少拥堵等),参考如下示意图(来源:维基百科):
强缓存
强缓存两个相关字段,Expires,Cache-Control。
强缓存分为两种情况,一种是发送HTTP请求,一种不需要发送。
首先检查强缓存,这个阶段不需要发送HTTP请求。通过查找不同的字段来进行,不同的HTTP版本所以不同。
HTTP1.0版本,使用的是Expires,HTTP1.1使用的是Cache-Control
Expires
Expires即过期时间,时间是相对于服务器的时间而言的,存在于服务端返回的响应头中,在这个过期时间之前可以直接从缓存里面获取数据,无需再次请求。比如下面这样:
Expires:Mon, 29 Jun 2020 11:10:23 GMT
表示该资源在2020年7月29日11:10:23过期,过期时就会重新向服务器发起请求。
这个方式有一个问题:服务器的时间和浏览器的时间可能并不一致,所以HTTP1.1提出新的字段代替它。
Cache-Control
HTTP1.1版本中,使用的就是该字段,这个字段采用的时间是过期时长,对应的是max-age。
Cache-Control:max-age=6000
上面代表该资源返回后6000秒,可以直接使用缓存。
当然了,它还有其他很多关键的指令,梳理了几个重要的
注意点:
当Expires和Cache-Control同时存在时,优先考虑Cache-Control。
当然了,当缓存资源失效了,也就是没有命中强缓存,接下来就进入协商缓存
协商缓存
强缓存失效后,浏览器在请求头中携带响应的缓存Tag来向服务器发送请求,服务器根据对应的tag,来决定是否使用缓存。
缓存分为两种,Last-Modified 和 ETag。两者各有优势,并不存在谁对谁有绝对的优势,与上面所讲的强缓存两个Tag所不同。
Last-Modified
这个字段表示的是最后修改时间。在浏览器第一次给服务器发送请求后,服务器会在响应头中加上这个字段。
浏览器接收到后,如果再次请求,会在请求头中携带If-Modified-Since字段,这个字段的值也就是服务器传来的最后修改时间。
服务器拿到请求头中的If-Modified-Since的字段后,其实会和这个服务器中该资源的最后修改时间对比:
如果请求头中的这个值小于最后修改时间,说明是时候更新了。返回新的资源,跟常规的HTTP请求响应的流程一样。
否则返回304,告诉浏览器直接使用缓存。
ETag
ETag是服务器根据当前文件的内容,对文件生成唯一的标识,比如MD5算法,只要里面的内容有改动,这个值就会修改,服务器通过把响应头把该字段给浏览器。
浏览器接受到ETag值,会在下次请求的时候,将这个值作为If-None-Match这个字段的内容,发给服务器。
服务器接收到If-None-Match后,会跟服务器上该资源的ETag进行比对
如果两者一样的话,直接返回304,告诉浏览器直接使用缓存
如果不一样的话,说明内容更新了,返回新的资源,跟常规的HTTP请求响应的流程一样
两者对比
性能上,Last-Modified优于ETag,Last-Modified记录的是时间点,而Etag需要根据文件的MD5算法生成对应的hash值。
精度上,ETag优于Last-Modified。ETag按照内容给资源带上标识,能准确感知资源变化,Last-Modified在某些场景并不能准确感知变化,比如
编辑了资源文件,但是文件内容并没有更改,这样也会造成缓存失效。
Last-Modified 能够感知的单位时间是秒,如果文件在 1 秒内改变了多次,那么这时候的 Last-Modified 并没有体现出修改了。
最后,如果两种方式都支持的话,服务器会优先考虑ETag。
总结
缓存是一种保存资源副本并在下次请求时直接使用该副本的技术。当 web 缓存发现请求的资源已经被存储,它会拦截请求,返回该资源的拷贝,而不会去源服务器重新下载。这样带来的好处有:缓解服务器端压力,提升性能(获取资源的耗时更短了)。对于网站来说,缓存是达到高性能的重要组成部分。缓存需要合理配置,因为并不是所有资源都是永久不变的:重要的是对一个资源的缓存应截止到其下一次发生改变(即不能缓存过期的资源)。
HTTP 缓存怎么做?
强缓存:
Expires或Cache-Control
协商缓存:
第一对:Last-Modified、If-Modified-Since
第二对:ETag、If-None-Match
http缓存都是从第二次请求开始的。第一次请求资源时,服务器返回资源,并在respone header头中回传资源的缓存参数;第二次请求时,浏览器判断这些请求参数,命中强缓存就直接200,否则就把请求参数加到request header头中传给服务器,看是否命中协商缓存,命中则返回304,否则服务器会返回新的资源。
浏览器第一次向一个web服务器发起http
请求后,服务器会返回请求的资源,并且在响应头中添加一些有关缓存的字段如:Cache-Control
、Expires
、Last-Modified
、ETag
、Date
等等。之后浏览器再向该服务器请求该资源就可以视情况使用强缓存和协商缓存。
下面假定浏览器已经访问了服务器,服务器返回了缓存相关的头部字段且浏览器已对相关资源做好缓存。通过下图来分析强缓存和协商缓存:
强缓存
如图红线所示的过程代表强缓存。用户发起了一个http
请求后,浏览器发现先本地已有所请求资源的缓存,便开始检查缓存是否过期。有两个http头部字段控制缓存的有效期:Expires
和Cache-Control
,浏览器是根据以下两步来判定缓存是否过期的:
Cache-Control
的s-maxage
或max-age
指令,若有,则使用响应报文生成时间Date + s-maxage/max-age
获得过期时间,再与当前时间进行对比(s-maxage
适用于多用户使用的公共缓存服务器);Cache-Control
的s-maxage
或max-age
指令,则比较Expires
中的过期时间与当前时间。Expires
是一个绝对时间。注意,在HTTP/1.1中,当首部字段Cache-Control
有指定s-maxage
或max-age
指令,比起首部字段Expires
,会优先处理s-maxage
或max-age
。
另外下面列几个Cache-Control
的常用指令:
max-age=xxx
: 缓存的内容将在 xxx 秒后失效no-cache
:含义是不使用本地缓存,需要使用协商缓存,也就是先与服务器确认缓存是否可用。no-store
:所有内存都不会进行缓存。public
:表明客户端和代理服务器都可以缓存,适用于公共缓存服务器的情况。private
:表明只有客户端可以缓存。经过上述两步判断后,若缓存未过期,返回状态码为200
,则直接从本地读取缓存,这就完成了整个强缓存过程;如果缓存过期,则进入协商缓存或服务器返回新资源过程。
协商缓存
当浏览器发现缓存过期后,缓存并不一定不能使用了,因为服务器端的资源可能仍然没有改变,所以需要与服务器协商,让服务器判断本地缓存是否还能使用。此时浏览器会判断缓存中是否有ETag
或Last-Modified
字段,如果没有,则发起一个http请求,服务器根据请求返回资源;如果有这两个字段,则在请求头中添加If-None-Match
字段(有ETag
字段的话添加)、If-Modified-Since
字段(有Last-Modified
字段的话添加)。注意:如果同时发送If-None-Match
、If-Modified-Since
字段,服务器只要比较If-None-Match
和ETag
的内容是否一致即可;如果内容一致,服务器认为缓存仍然可用,则返回状态码304
,浏览器直接读取本地缓存,这就完成了协商缓存的过程,也就是图中的蓝线;如果内容不一致,则视情况返回其他状态码,并返回所请求资源。下面详细解释下这个过程:
1.ETag
和If-None-Match
二者的值都是服务器为每份资源分配的唯一标识字符串。
ETag
字段。资源更新时,服务器端的ETag
值也随之更新;If-None-Match
字段,它的值就是上次响应报文中的ETag
的值;ETag
与If-None-Match
的值是否一致,如果不一致,服务器则接受请求,返回更新后的资源;如果一致,表明资源未更新,则返回状态码为304
的响应,可继续使用本地缓存,要注意的是,此时响应头会加上ETag
字段,即使它没有变化。2.Last-Modified
和If-Modified-Since
二者的值都是GMT格式的时间字符串。
Last-Modified
字段,表明该资源最后一次的修改时间;If-Modified-Since
字段,它的值就是上次服务器响应报文中的Last-Modified
的值;Last-Modified
与If-Modified-Since
的值是否一致,如果不一致,服务器则接受请求,返回更新后的资源;如果一致,表明资源未更新,则返回状态码为304
的响应,可继续使用本地缓存,与ETag
不同的是:此时响应头中不会再添加Last-Modified
字段。3.ETag
较之Last-Modified
的优势
以下内容引用于:http协商缓存VS强缓存
你可能会觉得使用Last-Modified
已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要ETag
呢?HTTP1.1
中ETag
的出现主要是为了解决几个Last-Modified
比较难解决的问题:
GET
;If-Modified-Since
能检查到的粒度是s级的,这种修改无法判断(或者说UNIX
记录MTIME
只能精确到秒);这时,利用ETag
能够更加准确的控制缓存,因为ETag
是服务器自动生成的资源在服务器端的唯一标识符,资源每次变动,都会生成新的ETag
值。Last-Modified
与ETag
是可以一起使用的,但服务器会优先验证ETag
。
首先检查Cache-Control,看强缓存是否可用。如果可用的话,直接使用,否则进入协商缓存,发送HTTP请求,服务器通过请求头中的If-Modified-Since或者If-None-Match字段检查资源是否更新。资源更新,返回资源和200状态码。否则,返回304,直接告诉浏览器直接从缓存中去资源
为什么要使用HTTP缓存 ?
不想使用缓存的几种方式:
1、Ctrl + F5强制刷新,都会直接向服务器提取数据。
2、按F5刷新或浏览器的刷新按钮,默认加上Cache-Control:max-age=0,即会走协商缓存。
3、在IE浏览器下不想使用缓存的做法:打开IE,点击工具栏上的工具->Internet选项->常规->浏览历史记录 设置. 选择“从不”,然后保存。最后点击“删除”把Internet临时文件都删掉 (IE缓存的文件就是Internet临时文件)。
1)物理层(Physical Layer)
2)数据链路层(Data Link Layer)
基本数据单位为帧;
主要的协议:以太网协议;
两个重要设备名称:网桥和交换机
数据链路层在物理层提供的服务的基础上为网络层提供可靠的数据传输;
3)网络层(Network Layer)路径选择、路由及逻辑寻址
网络层中涉及众多的协议,其中包括最重要的协议,也是TCP/IP的核心协议——IP协议。IP协议非常简单,仅仅提供不可靠、无连接的传送服务。IP协议的主要功能有:无连接数据报传输、数据报路由选择和差错控制
1> 网络层负责对子网间的数据包进行路由选择。此外,网络层还可以实现拥塞控制、网际互连等功能;
2> 基本数据单位为IP数据报;
3> 包含的主要协议:
IP协议(Internet Protocol,因特网互联协议);
ICMP协议(Internet Control Message Protocol,因特网控制报文协议);
ARP协议(Address Resolution Protocol,地址解析协议);
RARP协议(Reverse Address Resolution Protocol,逆地址解析协议)。
4> 重要的设备:路由器。
4)传输层
在这一层,信息传送的协议数据单元称为段或报文。 网络层只是根据网络地址将源结点发出的数据包传送到目的结点,而传输层则负责将数据可靠地传送到相应的端口
1> 传输层负责将上层数据分段并提供端到端的、可靠的或不可靠的传输以及端到端的差错控制和流量控制问题;
2> 运输层主要使用以下两种协议
传输控制协议 TCP–提供面向连接的,可靠的数据传输服务。
用户数据协议 UDP–提供无连接的,尽最大努力的数据传输服务(不保证数据传输的可靠性)。
3> 重要设备:网关。
5)会话层
会话层管理主机之间的会话进程,即负责建立、管理、终止进程之间的会话
6)表示层
表示层对上层数据或信息进行变换以保证一个主机应用层信息可以被另一个主机的应用程序理解。表示层的数据转换包括数据的加密、压缩、格式转换等。
7)应用层
为操作系统或网络应用程序提供访问网络服务的接口
会话层、表示层和应用层重点:
1> 数据传输基本单位为报文;
2> 包含的主要协议:FTP(文件传送协议)、Telnet(远程登录协议)、DNS(域名解析协议)、SMTP(邮件传送协议),POP3协议(邮局协议),HTTP协议(Hyper Text Transfer Protocol),简单网络管理协议SNMP。
用到了UDP协议的SNMP和DNS
三次握手:
第一次握手:客户端发送syn包(seq=x)到服务器,并进入SYN_SEND(发送)状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(seq=y),即SYN+ACK包,此时服务器进入SYN_RECV(接收)状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(已建立)状态,完成三次握手。
第三次握手的作用是客户端对服务器端的初始序号的确认。如果只使用两次握手,那么服务器就没有办法知道自己的序号是否 已被确认。同时这样也是为了防止失效的请求报文段被服务器接收,而出现错误的情况
说明:
1)SYN和ACK是标志位(0/1)(ACK=1表明ack有效),seq是序列号,ack是确认号。2)给对方的确认方式就是把对方传来的seq+1并赋给ack。
四次挥手:
第一次挥手:主动关闭方发送一个FIN,用来关闭主动方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方:我已经不 会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可 以接受数据。
第二次挥手:被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1。
第三次挥手:被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了。
第四次挥手:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,至此,完成四次挥手。
TCP 使用四次挥手的原因是因为 TCP 的连接是全双工的,所以需要双方分别释放到对方的连接,单独一方的连接释放,只代 表不能再向对方发送数据,连接处于的是半释放的状态
为什么要三次握手?
防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误
在只有两次"握手"的情形下,假设Client想跟Server建立连接,但是却因为中途连接请求的数据报丢失了,故Client端不得不重新发送一遍;这个时候Server端仅收到一个连接请求,因此可以正常的建立连接。但是,有时候Client端重新发送请求不是因为数据报丢失了,而是有可能数据传输过程因为网络并发量很大在某结点被阻塞了,这种情形下Server端将先后收到2次请求,并持续等待两个Client请求向他发送数据…问题就在这里,Cient端实际上只有一次请求,而Server端却有2个响应,极端的情况可能由于Client端多次重新发送请求数据而导致Server端最后建立了N多个响应在等待,因而造成极大的资源浪费!所以,"三次握手"很有必要!
为什么要四次挥手?
试想一下,假如现在你是客户端你想断开跟Server的所有连接该怎么做?第一步,你自己先停止向Server端发送数据,并等待Server的回复。但事情还没有完,虽然你自身不往Server发送数据了,但是因为你们之前已经建立好平等的连接了,所以此时他也有主动权向你发送数据;故Server端还得终止主动向你发送数据,并等待你的确认。其实,说白了就是保证双方的一个合约的完整执行!
区别:TCP是面向连接的,可靠的字节流服务;UDP是面向无连接的,不可靠的数据报服务。
可靠传输的实现方法:
序列号 确认应答 超时重传 拥塞控制
确认应答机制&序列号
TCP将每个字节的数据都进行了编号,即为序列号。
每一个ACK都带有对应的确认序列号,意思是告诉发送者,我已经收到了哪些数据;;下一次你从哪里开始发。
超时重传&序列号
主机A发送数据给B之后, 可能因为网络拥堵等原因, 数据无法到达主机B; 如果主机A在一个特定时间间隔内没有收到B发来的确认应答, 就会进行重发;
主机A未收到B发来的确认应答,也可能是因为ACK丢失了,因此主机B会收到很多重复数据.。那么TCP协议需要能够识别出那些包是重复的包,,并且把重复的丢弃掉.,这时候我们可以利用序列号, 就可以很容易做到去重的效果。
拥塞控制
拥塞控制机制,在网络拥塞的时候会控制发送数据的速率,有助于减少数据包的丢失和减轻网络中的拥塞程度。
每次发送数据包的时候, 将拥塞窗口和接收端主机反馈的窗口大小做比较, 取较小的值作为实际发送的窗口。
提高传输效率:滑动窗口、流量控制、延迟应答、捎带应答
滑动窗口机制
流量控制
流量控制机制,保证了通信双方的发送和接收速率相同。如
果接收方可接收的缓存很小时,发送方会降低发送 速率,避免因为缓存填满而造成的数据包的丢失。
TCP对应的协议:
(1) FTP:定义了文件传输协议,使用21端口。
(2) Telnet:一种用于远程登陆的端口,使用23端口,用户可以以自己的身份远程连接到计算机上,可提供基于DOS模式下的通信服务。
(3) SMTP:邮件传送协议,用于发送邮件。服务器开放的是25号端口。
(4) POP3:它是和SMTP对应,POP3用于接收邮件。POP3协议所用的是110端口。
(5)HTTP:是从Web服务器传输超文本到本地浏览器的传送协议。
UDP对应的协议:
(1) DNS:用于域名解析服务,将域名地址转换为IP地址。DNS用的是53号端口。
(2) SNMP:简单网络管理协议,使用161号端口,是用来管理网络设备的。由于网络设备很多,无连接的服务就体现出其优势。
(3) TFTP(Trival File Tran敏感词er Protocal),简单文件传输协议,该协议在熟知端口69上使用UDP服务。
面向连接和非面向连接的服务的特点是什么?
面向连接的服务,通信双方在进行通信之前,要先在双方建立起一个完整的可以彼此沟通的通道,在通信过程中,整个连接的情况一直可以被实时地监控和管理。
非面向连接的服务,不需要预先建立一个联络两个通信节点的连接,需要通信的时候,发送节点就可以往网络上发送信息,让信息自主地在网络上去传,一般在传输的过程中不再加以监控。
http通信过程
一、TCP连接
二、浏览器向服务器发送请求命令
例如:GET/sample/hello.jsp HTTP/1.1
HTTP1.0:客户端每次请求都要建议一次独立的链接,在处理完本次请求后会主动释放链接。
HTTP1.1:一次链接可以处理多个请求,请求可以重叠进行。
请求命令:
GET
GET方法是默认的HTTP请求方法,我们日常用GET方法来提交表单数据,然而用GET方法提交的表单数据只经过了简单的编码,
同时它将作为URL的一部分向Web服务器发送,因此,如果使用GET方法来提交表单数据就存在着安全隐患上。所以GET方法不
安全。
POST
POST方法是GET方法的一个替代方法,它主要是向Web服务器提交表单数据,尤其是大批量的数据。POST方法克服了GET方法
的一些缺点。通过POST方法提交表单数据时,数据不是作为URL请求的一部分而是作为标准数据传送给Web服务器,这就克服了
GET方法中的信息无法保密和数据量太小的缺点。因此,出于安全的考虑以及对用户隐私的尊重,通常表单提交时采用POST方法。
PUT
用于修改某个内容
DELETE
删除某些内容
CONNECT
用于代理传输
等等
三、浏览器发送请求头信息
浏览器发送其请求命令之后,还要以头信息的形式向Web服务器发送一些别的信息,之后浏览器发送了一空白行来通知服务器,它
已经结束了该头信息的发送。
四、服务器应答
例如:HTTP/1.1 200 OK
应答的第一部分是协议的版本号和应答状态码
HTTP应答码:
1XX-信息类(Information),表示收到Web浏览器请求,正在进一步的处理中
2XX-成功类(Successful),表示用户请求被正确接收,理解和处理例如:200 OK
3XX-重定向类(Redirection),表示请求没有成功,客户必须采取进一步的动作。
4XX-客户端错误(Client Error),表示客户端提交的请求有错误 例如:404 NOT Found,意味着请求中所引用的文档不存在。
5XX-服务器错误(Server Error)表示服务器不能完成对请求的处理:如 500
五、服务器发送应答信息
六、服务器向浏览器发送数据
七、服务器关闭TCP连接 tcp四次挥手
http常见头部字段
通用首部字段
1.请求指令cache-control : no-cache no-store max-age
响应指令cache-control : no-cache no-store max-age s-maxage public private
2.connection: keep-alive close
3.Date 首部字段 Date 表明创建 HTTP 报文的日期和时间。
请求首部字段
1.Accept 首部字段可通知服务器,用户代理能够处理的媒体类型及媒体
类型的相对优先级,若想要给显示的媒体类型增加优先级,则使用 q= 来额外表示权重值
1,用分号(;)进行分隔。权重值 q 的范围是 0~1(可精确到小数点
后 3 位),且 1 为最大值。不指定权重 q 值时,默认权重为 q=1.0。
2.Accept-Charset 首部字段可用来通知服务器用户代理支持的字符集及
字符集的相对优先顺序。
3.Accept-Encoding 首部字段用来告知服务器用户代理支持的内容编码及
内容编码的优先级顺序。
4. Accept-Language 首部字段 Accept-Language 用来告知服务器用户代理能够处理的自然
语言集(指中文或英文等)
5.Authorization 首部字段 Authorization 是用来告知服务器,用户代理的认证信息(证
书值)。
6.Host 首部字段 Host 会告知服务器,请求的资源所处的互联网主机名和端
口号。
7.If-Modified-Since
8.If-None-Match
9.User-Agent首部字段 User-Agent 会将创建请求的浏览器和用户代理名称等信息传
达给服务器
响应首部字段
1.Accept-Ranges 首部字段 Accept-Ranges 是用来告知客户端服务器是否能处理范围请求,以指定获取服务器端某个部分的资源。可指定的字段值有两种,可处理范围请求时指定其为 bytes,反之则
指定其为 none。
2.Age 首部字段 Age 能告知客户端,源服务器在多久前创建了响应。字段值
的单位为秒。
3.ETag 首部字段 ETag 能告知客户端实体标识。服务器会为每份资源分配对应的 ETag
值。资源改变,Etag值也会变。
4.Location 几乎所有的浏览器在接收到包含首部字段 Location 的响应后,都会强
制性地尝试对已提示的重定向资源的访问
实体首部字段
1.Allow 首部字段 Allow 用于通知客户端能够支持 Request-URI 指定资源的所有 HTTP 方法。当服务器接收到不支持的 HTTP 方法时,会以状态码405 Method Not Allowed 作为响应返回
2.Content-Type首部字段 Content-Type 说明了实体主体内对象的媒体类型段 Accept 一样,字段值用 type/subtype 形式
3.Expires 首部字段 Expires 会将缓存资源失效的日期告知客户端。
4.Last-Modified 首部字段 Last-Modified 指明资源最终修改的时间。
Cookie首部字段
set-cookie和cookie
set-cookie中设置httpOnly
Cookie 的 HttpOnly 属性是 Cookie 的扩展功能,它使 JavaScript 脚本
无法获得 Cookie。其主要目的为防止跨站脚本攻击(Cross-site
scripting,XSS)对 Cookie 的信息窃取。
HTTPS
原本HTTP先和TCP(假定传输层是TCP协议)直接通信,而加了SSL后,就变成HTTP先和SSL通信,再由SSL和TCP通信,相当于SSL被嵌在了HTTP和TCP之间。
大致流程:客户端拿到服务器的公钥(是正确的),然后客户端随机生成一个对称加密的秘钥,使用该公钥加密,传输给服务端,服务端再通过解密拿到该对称秘钥,后续的所有信息都通过该对称秘钥进行加密解密,完成整个HTTPS的流程。
第三方认证,最重要的是数字签名,避免了获取的公钥是中间人的。
TLS/SSL 的功能实现主要依赖于三类基本算法:散列函数 、对称加密和非对称加密,其利用非对称加密实现身份认证和密钥协商,对称加密算法采用协商的密钥对数据加密,基于散列函数验证信息的完整性。
Https 的加密机制是一种共享密钥加密和公开密钥加密并用的混合加密机制。
HTTPS采用的加密方式: 在交换密钥阶段使用公开密钥加密方式,之后建立通信交换报文阶段则使用共享密钥加密方式
将对称加密的密钥使用非对称加密的公钥进行加密,然后再发送出去,然后接收方使用自己的私钥进行解密得到对称加密的密钥
HTTP 默认工作在 TCP 协议 80 端口,用户访问网站 http:// 打头的都是标准 HTTP 服务。
HTTP 协议以明文方式发送内容,不提供任何方式的数据加密,不适合传输一些敏感信息
HTTPS(Hypertext Transfer Protocol Secure:超文本传输安全协议)是一种透过计算机网络进行安全通信的传输协议。HTTPS 经由 HTTP 进行通信,但利用 SSL/TLS 来加密数据包。HTTPS 开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性。
HTTPS 默认工作在 TCP 协议443端口,它的工作流程一般如以下方式:
1、TCP 三次同步握手
2、客户端验证服务器数字证书
3、DH 算法协商对称加密算法的密钥、hash 算法的密钥
4、SSL 安全加密隧道协商完成
5、网页以加密的方式传输,用协商的对称加密算法和密钥加密,保证数据机密性;用协商的hash算法进行数据完整性保护,保证数据不被篡改。
HTTP 与 HTTPS 区别
对称加密
加密和解密用同一个秘钥的加密方式叫做对称加密。Client客户端和Server端共用一套密钥,这样子的加密过程似乎很让人理解,但是随之会产生一些问题。
问题一: WWW万维网有许许多多的客户端,不可能都用秘钥A进行信息加密,这样子很不合理,所以解决办法就是使用一个客户端使用一个密钥进行加密。
问题二:既然不同的客户端使用不同的密钥,那么对称加密的密钥如何传输? 那么解决的办法只能是一端生成一个秘钥,然后通过HTTP传输给另一端,那么这样子又会产生新的问题。
问题三: 这个传输密钥的过程,又如何保证加密?如果被中间人拦截,密钥也会被获取, 那么你会说对密钥再进行加密,那又怎么保存对密钥加密的过程,是加密的过程?
到这里,我们似乎想明白了,使用对称加密的方式,行不通,所以我们需要采用非对称加密
非对称加密
通过上面的分析,对称加密的方式行不通,那么我们来梳理一下非对称加密。采用的算法是RSA,所以在一些文章中也会看见传统RSA握手,基于现在TLS主流版本是1.2,所以接下来梳理的是TLS/1.2握手过程。
非对称加密中,我们需要明确的点是
有一对秘钥,公钥和私钥。
公钥加密的内容,只有私钥可以解开,私钥加密的内容,所有的公钥都可以解开,这里说的公钥都可以解开,指的是一对秘钥。
公钥可以发送给所有的客户端,私钥只保存在服务器端。
主要工作流程
梳理起来,可以把TLS 1.2 握手过程分为主要的五步
图片内容来自浪里行舟
步骤(1)
Client发起一个HTTPS请求,连接443端口。这个过程可以理解成是请求公钥的过程。
步骤(2)
Server端收到请求后,通过第三方机构私钥加密,会把数字证书(也可以认为是公钥证书)发送给Client。
步骤(3)
浏览器安装后会自动带一些权威第三方机构公钥,使用匹配的公钥对数字签名进行解密。
根据签名生成的规则对网站信息进行本地签名生成,然后两者比对。
通过比对两者签名,匹配则说明认证通过,不匹配则获取证书失败。
步骤(4)
在安全拿到服务器公钥后,客户端Client随机生成一个对称密钥,使用服务器公钥(证书的公钥)加密这个对称密钥,发送给Server(服务器)。
步骤(5)
Server(服务器)通过自己的私钥,对信息解密,至此得到了对称密钥,此时两者都拥有了相同的对称密钥。
接下来,就可以通过该对称密钥对传输的信息加密/解密啦,从上面图举个例子
Client用户使用该对称密钥加密’明文内容B’,发送给Server(服务器)
Server使用该对称密钥进行解密消息,得到明文内容B。
接下来考虑一个问题,如果公钥被中间人拿到纂改怎么办呢?
以下图片来自leocoder
客户端可能拿到的公钥是假的,解决办法是什么呢?
第三方认证
客户端无法识别传回公钥是中间人的,还是服务器的,这是问题的根本,我们是不是可以通过某种规范可以让客户端和服务器都遵循某种约定呢?那就是通过第三方认证的方式
在HTTPS中,通过 证书 + 数字签名来解决这个问题。
这里唯一不同的是,假设对网站信息加密的算法是MD5,通过MD5加密后,然后通过第三方机构的私钥再次对其加密,生成数字签名。
这样子的话,数字证书包含有两个特别重要的信息某网站公钥+数字签名
我们再次假设中间人截取到服务器的公钥后,去替换成自己的公钥,因为有数字签名的存在,这样子客户端验证发现数字签名不匹配,这样子就防止中间人替换公钥的问题。
那么客户端是如何去对比两者数字签名的呢?
浏览器会去安装一些比较权威的第三方认证机构的公钥,比如VeriSign、Symantec以及GlobalSign等等。
验证数字签名的时候,会直接从本地拿到相应的第三方的公钥,对私钥加密后的数字签名进行解密得到真正的签名。
然后客户端利用签名生成规则进行签名生成,看两个签名是否匹配,如果匹配认证通过,不匹配则获取证书失败。
数字签名作用
数字签名:将网站的信息,通过特定的算法加密,比如MD5,加密之后,再通过服务器的私钥进行加密,形成加密后的数字签名。
第三方认证机构是一个公开的平台,中间人可以去获取。
如果没有数字签名的话,这样子可以就会有下面情况
从上面我们知道,如果只是对网站信息进行第三方机构私钥加密的话,还是会受到欺骗。
因为没有认证,所以中间人也向第三方认证机构进行申请,然后拦截后把所有的信息都替换成自己的,客户端仍然可以解密,并且无法判断这是服务器的还是中间人的,最后造成数据泄露。
总结
HTTPS就是使用SSL/TLS协议进行加密传输
大致流程:客户端拿到服务器的公钥(是正确的),然后客户端随机生成一个对称加密的秘钥,使用该公钥加密,传输给服务端,服务端再通过解密拿到该对称秘钥,后续的所有信息都通过该对称秘钥进行加密解密,结合数字证书认证的方式,完成整个HTTPS的流程。
第三方认证,最重要的是数字签名,避免了获取的公钥是中间人的。
http1.0和http1.1的区别
1⃣️
2⃣️
3⃣️
4⃣️
5⃣️
http1.x版本问题
在传输数据过程中,所有内容都是明文,客户端和服务器端都无法验证对方的身份,无法保证数据的安全性。
HTTP/1.1 版本默认允许复用TCP连接,但是在同一个TCP连接里,所有数据通信是按次序进行的,服务器通常在处理完一个回应后,才会继续去处理下一个,这样子就会造成队头阻塞。
http/1.x 版本支持Keep-alive,用此方案来弥补创建多次连接产生的延迟,但是同样会给服务器带来压力,并且的话,对于单文件被不断请求的服务,Keep-alive会极大影响性能,因为它在文件被请求之后还保持了不必要的连接很长时间。
HTTP2.0和HTTP1.X相比的新特性
两个页面地址中的协议,域名,端口号一致,则表示同源。同源策略是一种安全协议。
指一段脚本只能读取来自同一来源的窗口和文档的属性。
同源策略的限制:不能通过ajax请求不同域的数据,不能通过脚本操作不同域下的DOM,
为什么要用同源策略
设置同源限制主要是为了安全,如果没有同源限制存在浏览器中的cookie等其他数据可以任意读取,不同域下DOM任意操作,ajax任意请求的话如果浏览了恶意网站那么就会泄漏这些隐私数据
违反浏览器同源策略的就是跨域。跨域本身就是就是为了保护浏览器的安全, 主要是用来防止 CSRF 攻击的
如何解决跨域问题
JSONP、CORS、通过修改document.domain来跨子域、使用window.name来进行跨域、HTML5中新引进的window.postMessage方法、在服务器上设置代理页面
1、JSONP
原理是:
通过标签的异步加载来实现的。
优点是兼容性好,简单易用,支持浏览器与服务器双向通信。缺点是只支持GET请求。
2、CORS
服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。
CORS的简单请求和非简单请求:
简单请求就是使用设定的请求方式请求数据
而非简单请求则是在使用设定的请求方式请求数据之前,先发送一个OPTIONS请求,看服务端是否允许客户端发送非简单请求.
只有"预检"通过后才会再发送一次请求用于数据传输
只要同时满足以下两大条件,就属于简单请求。
(1) 请求方法是以下三种方法之一:
HEAD,GET,POST
(2)Content-Type 的值仅限于下列三者之一
text/plain
multipart/form-data
application/x-www-form-urlencoded
「与JSONP对比」
3、通过修改document.domain来跨子域
将子域和主域的document.domain设为同一个主域.前提条件:这两个域名必须属于同一个基础域名!而且所用的协议,端口都要一致,否则无法利用document.domain进行跨域
主域相同的使用document.domain
4、使用window.name来进行跨域
window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的