赞
踩
1. 打开浏览器,地址栏输入域名 (如:blog.csdn.net)。
2. 浏览器根据域名解析IP地址(DNS域名解析)。
本地解析:
浏览器缓存 -》 系统缓存 -》 查找本地host文件 -》 本地DNS服务器缓存
互联网域名服务器解析:
-》 根域名服务器 -》 顶级域名服务器 -》 权威域名服务器
3. 浏览器获得域名对应的ip地址后 ,与WEB服务器建立TCP连接(TCP三次握手)
4. tcp连接建立后,浏览器给WEB服务器发送一个HTTP请求
5. 服务器端响应HTTP请求,返回HTTP报文
服务器端接受到请求,根据路径参数,经过后端的一些处理之后,把处理后的一个结果数据返回给浏览器,如果是一个完整的网页,就是把完整的html页面代码返回给浏览器。
6. 浏览器解析和渲染页面
浏览器拿到HTML文件后,开始解析HTML代码,遇到静态资源时,就向服务器端去请求下载。
浏览器利用自己内部的工作机制,把请求到的静态资源和HTML代码进行渲染,呈现给用户。
7. 关闭TCP连接(四次挥手)
下面是每一步骤的详细解释
目录
三、 浏览器获得域名对应的ip地址后 ,与WEB服务器建立TCP连接(TCP三次握手)
3.2.1 源端口号source port 和 目的端口号destination port
3.2.2 序列号 Sequence Number(简写为seq)
3.2.3 确认序列号 Acknowledgment Number (简写为ack)
3.2.4 ACK 表示应答域有效 (ACK、SYN、FIN 是TCP首部的标志比特位,可设置为1)
3.4.2 确认应答ack+序列号seq(对数据包排序,避免数据重复发送和接收)
3.5 为什么TCP握手需要三次?为什么不是一次、两次握手?
3.6 TCP三次握手有什么缺陷?( 引起SYN Flood)
3.9 如何区分一个数据报是本次连接产生的还是上一次由于网络拥塞延迟到达的?
四、tcp连接建立后,浏览器给WEB服务器发送一个HTTP请求
4.2 HTTP协议是怎么实现的(即HTTP协议工作过程)?
4.5 HTTP的缓存策略(比如缓存的关键Header是什么)?
4.7 HTTPS协议是怎么实现的(加密方式以及加密过程)?
5.2 响应行中HTTP协议版本号HTTP 1.0和HTTP 1.1的主要区别是什么?
6.2 DOM树、CSSOM树、JavaScript的顺序问题
6.3 我们为什么一再强调将css放在头部,将js文件放在尾部?
7.2 为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
(1)是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称,用于在数据传输时对计算机的定位标识。
(2)IP地址用来建立互联网通信,它具有唯一性,只有知道对方主机的IP地址,我们才能和对方主机互相通信。而这一串IP地址是非常难记的.这时候域名登场了。
域名(Domain Name)是IP地址的映射,每个域名对应一个唯一的IP地址
(4)以淘宝为例,www.taobao.com就是域名,但计算机并不能直接根据域名找到淘宝,必须转化成101.89.125.239(IPV4)或240e:e1:f300:1:3::3f9(IPV6)这样的IP地址才能准确读取,因此出现了DNS域名解析。
域名分成顶级域名(又叫一级域名),二级域名,三级域名等,比较少有四级域名
(1)域名组成:一个完整的域名由二个或二个以上部分组成,各部分之间用英文的句号"."来分隔。
最右边部分称为顶级域名(最高级的域名,就是网址的最后一个部分。例如:www.example.com的顶级域名就是.com);
顶级域名的左边部分字符串到下个"."为止称为二级域名;
二级域名的左边部分称为三级域名,以此类推,每一级的域名控制它下一级域名的分配。
全世界域名的最高管理机构:ICANN。ICANN负责全世界域名系统的运作,它的一项主要工作:规定顶级域名(TLD)
(1)顶级域名分为两类:
一是国家顶级域名(国别顶级域名:代表不同的国家和地区),例如中国是cn,美国是us,日本是jp等;
二是国际顶级域名(一般性顶级域名),例如表示工商企业的.Com,表示网络提供商的.net,表示非盈利组织的.org等
(2)每个顶级域名都找一个托管商
例如:.cn的域名托管商就是中国互联网络信息中心,它决定了.cn域名的各种政策
Verisign是ICANN最大的托管商,托管了.com、.net、.name、.gov四个一般性顶级域名 以及 .cc和.tv两个国别顶级域名等
(1)根域名(用于DNS查询,即获取ip地址)
由于ICANN管理所有的顶级域名,所以它是最高一级的域名节点,被称为根域名。
例如:www.example.com 被写成 www.example.com. 最后多出一个点,这个点就是根域名.
(2)根域名服务器
由于根域名管理所有的顶级域名,因此所有的域名查询都必须先查询根域名(只有根域名才会告诉你,某个顶级域名由哪台服务器管理),
即查询ICANN的根域名列表(ICANN维护者一张根域名列表,记载了顶级域名和对应的托管商),保存根域名列表的服务器就叫根域名服务器
为了便于查询,本机都保存一份根域名服务器的ip地址的缓存。
扩展:规定全球由13个根域名服务器,编号从a~m(即a.root-servers.net 一直到 m.root-servers.net)
属于第三步:根域名服务器查询(即本地解析和本地DNS解析之后)
根域名服务器不会直接解析域名,而是把不同的解析请求分配给下面的其它服务器来完成,下面是dns域名系统的树状结构图:
以www.taobao.com为例:
(1)当信息传递给递归服务器后,会根据本机内置的根域名服务器ip地址,寻求根域名服务器的帮助
(2)当根域名接收到本地dns的解析请求后,获知后缀是.com,于是就把负责.com的顶级域名服务器ip地址返回给本地dns(图中为③和④)。
(3)本地dns获得返回的ip地址,再去找对应的顶级域名服务器,顶级域名又把负责该域名的权威服务器ip返回给本地dns(图中为⑤和⑥)。
(4)本地dns根据ip找到对应的权威服务器,权威服务器把对应的主机ip返回给本地dns,至此完成了域名解析的全过程(图中为⑦和⑧)
(5)本地dns将获取的ip地址给浏览器,浏览器根据获取的ip地址与目标服务器建立连接
要上网必须通过DNS服务器进行解析,针对全世界所有人,因此DNS服务器必须是高可用分布式的。
浏览器缓存 -》 系统缓存 -》 查找本地host文件 -》本地DNS服务器 -》 根域名服务器 -》 顶级域名服务器 -》 权威域名服务器
用户在本机浏览器输入www.taobao.com后,计算机会先在本地进行解析(图中为①),这里会分成三小步:
(1)先到浏览器的DNS缓存中查询是否有对应记录,如有则直接返回ip地址,完成解析,如果没有则下一步;
(缓存的时间比较短,大概只有1分钟,且只能容纳1000条缓存,看自身的缓存中是否是有域名对应的条目,而且没有过期,如果有且没有过期则解析到此结束。)
(2)接着判断:浏览器是否进行域名直接查询。如果有的话,会直接连到服务商提供的DNS服务器上,并返回IP;
如果没有,则继续查询操作系统的缓存:如有则直接返回ip地址,完成解析,如果没有则下一步;
(3)最后查看本地host文件,比如windows的host文件一般位于“C:\Windows\System32\drivers\etc”,如果这里也没有的话就需要到本地dns服务器上查找了。
包括两部分:缓存服务器和递归服务器。
(1)缓存服务器有2种,
一种是公共DNS服务器,比如114 DNS(114.114.114.114)、Google DNS(8.8.8.8);
另一种是本地运营商提供的DNS服务器,比如电信的DNS服务器。
普通用户使用的都是运营商的本地域名服务器,这些服务器一般架设在离用户不远的地方,而且性能都很好,
所以一般都会缓存域名解析结果,大约80%的域名解析都会在这一步完成(图中为②)。
注:本地DNS获取到相应域名的ip后,会将该ip缓存到缓存中(下次有相同域名访问时,会从缓存中取到对应域名的ip,提高解析性能)
(2)如果缓存服务器无法找到对应IP,则会把信息传递给递归服务器。
dns域名服务器一般分3种,分别是根域名服务器(.)、顶级域名服务器(例:.com)、权威域名服务器。
根域名服务器不会直接解析域名,而是把不同的解析请求分配给下面的其它服务器来完成,下面是dns域名系统的树状结构图:
以www.taobao.com为例,
(1)当信息传递给递归服务器后,会根据本机内置的根域名服务器ip地址,寻求根域名服务器的帮助
(2)当根域名接收到本地dns的解析请求后,获知后缀是.com,于是就把负责.com的顶级域名服务器ip地址返回给本地dns(图中为③和④)。
(3)本地dns获得返回的ip地址,再去找对应的顶级域名服务器,顶级域名又把负责该域名的权威服务器ip返回给本地dns(图中为⑤和⑥)。
(4)本地dns根据ip找到对应的权威服务器,权威服务器把对应的主机ip返回给本地dns,至此完成了域名解析的全过程(图中为⑦和⑧)
(5)本地dns将获取的ip地址给浏览器,浏览器根据获取的ip地址与目标服务器建立连接
我们只考虑第三种情况(即缓存中没有查找到域名对应ip的情况),通过根域名服务器查找
第(4)(5)(6)步实现就近访问、负载均衡
输入域名: www.taobao.com
(1)当信息传递给递归服务器(属于本地DNS服务器)后,会根据本机内置的根域名服务器ip地址,寻求根域名服务器的帮助
(2)当根域名接收到本地dns的解析请求后,获知后缀是.com,于是就把负责.com的顶级域名服务器ip地址返回给本地dns
(3)本地dns获得返回的ip地址,再去找对应的顶级域名服务器,顶级域名又把负责该域名的权威服务器ip返回给本地dns
(4)本地dns根据ip找到对应的权威服务器,权威服务器返回别名CNAME(不是返回ip)
(5)本地dns根据获取的别名CNAME访问全局负载均衡器GSLB,
(6)全局负载均衡器根据CNAME,通过查看 请求它的DNS本地运营商 所在的地址,获取本地运营商的地址,返回与用户相同运营商,并且离用户最近的机房ip给本地DNS
(7)本地dns将获取的ip地址给浏览器,浏览器根据获取的ip地址与目标服务器建立连接
TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
通俗一点的讲,TCP 就是一个双方通信的一个规范标准(协议)。
我们在学习 TCP 握手过程之前,首先必须了解 TCP 报文头部的一些标志信息,因为在 TCP 握手的过程中,会使用到这些报文信息。
source port
和 目的端口号destination port
源端口号就是指本地端口,目的端口就是远程端口。
一个数据包(pocket)被解封装成数据段(segment)后就会涉及到连接上层协议的端口问题。
可以这么理解,发送方有很多的窗户,接收方也有很多的窗户,这些窗口都标有不同的端口号,源端口号和目的端口号就分别代表从哪个规定的口窗发送到对方接收的窗口。
不同的应用程度都有着不同的端口。
扩展:应用程序的端口号和应用程序所在主机的 IP 地址统称为 socket(套接字),IP:端口号, 在互联网上 socket 唯一标识每一个应用程序,源端口+源IP+目的端口+目的IP称为”套接字对“,一对套接字就是一个连接,一个客户端与服务器之间的连接。
Sequence Number(简写为seq)
用于 TCP 通信过程中某一传输方向上字节流的每个字节的编号,为了确保数据通信的有序性,避免网络中乱序的问题。接收端根据这个编号进行确认,保证分割的数据段在原始数据包的位置。(发送方的数据是怎样一个顺序,到了接受方也要确保是这个顺序)
Acknowledgment Number (简写为ack)
接收端每接收一段,之后就想要的下一段的序列号就称为「确认序列号」。确认序号应当是上次已成功收到数据字节序号seq加1,只有当标志位中的 ACK 标志为 1 时该确认序列号ack才有效。主要用来解决不丢包的问题。
若确认号ack=N,则表明:到序号N-1为止的所有数据都已正确收到。
这个标识可以理解为发送端发送数据到接收端,发送的时候 ACK 为 0,标识接收端还未应答,一旦接收端接收数据之后,就将 ACK 置为 1,发送端接收到之后,就知道了接收端已经接收了数据。
就是说前面所说的TCP应答号将会包含在 TCP 数据包中;有两个取值:0 和 1,为 1 的时候表示应答域有效,反之为 0;
是 TCP 握手的发送的第一个数据包。
用来建立 TCP 的连接。SYN 标志位和 ACK 标志位搭配使用,当连接请求的时候,SYN=1,ACK=0;连接被响应的时候,SYN=1,ACK=1;
这个标志的数据包经常被用来进行端口扫描。扫描者发送一个只有 SYN 的数据包,如果对方主机响应了一个数据包回来 ,就表明这台主机存在这个端口。看下面动画
发送端只剩最后的一段数据了,同时要告诉接收端后边没有数据可以接受了。所以用FIN=1标识一下,接收端看到这个FIN之后,哦!这是接受的最后的数据,接受完就关闭了。
发送FIN标志位的 TCP 数据包后,连接将被断开。这个标志的数据包也经常被用于进行端口扫描。
TCP 三次握手的过程掌握最重要的两点就是客户端和服务端状态的变化,另一个是三次握手过程标志信息的变化。
下图为三次握手的详细过程:
客户端处于 closed(关闭)
状态,服务器处于 listen(监听)
状态。
客户端发送请求报文将
SYN = 1
同步序列号和初始化序列号seq = x
发送给服务端,发送完之后客户端处于SYN_Send发送等待
状态。
初始化序列号seq = x :当前发送的数据字节序号为x
服务端受到
SYN
请求报文之后,如果同意连接,会以自己的同步序列号SYN(服务端) = 1
、初始化序列号seq = y
和确认序列号(期望下次收到的数据包)ack = x+ 1
以及确认号ACK = 1
报文作为应答,服务器为SYN_Receive确认接收
状态。
初始化序列号seq = y :当前发送的数据字节序号为y
确认序列号 ack = x + 1 : 想要的下一段的序列号。确认序号应当是上次已成功收到数据字节序号seq加1
客户端接收到服务端的
SYN + ACK
之后,知道可以下次可以发送了下一序列的数据包了,然后发送同步序列号ack = y + 1
和数据包的序列号seq = x + 1
以及确认号ACK = 1
确认包作为应答,客户端转为established
状态。
初始化序列号seq = x+1 :当前发送的数据字节序号为x+1(客户端第一次发送的字节序号seq为x,所以下一次为x+1)
确认序列号 ack = y + 1 : 想要的下一段的序列号。确认序号应当是上次已成功收到数据字节序号seq加1,即y+1
目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP将丢弃这个报文段 和 不确认收到此报文段。
序列号的作用不仅仅是应答的作用,有了序列号能够将接收到的数据根据序列号排序,并且去掉重复序列号的数据
TCP给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。
当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。
TCP连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送 接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止
包丢失。TCP使用的流量控制协议是可变大小的滑动窗口协议。
接收方有即时窗口(滑动窗口),随ACK报文发送
当网络拥塞时,减少数据的发送。
拥塞控制主要是四个算法:1)慢启动,2)拥塞避免,3)拥塞发生,4)快速恢复。
发送方有拥塞窗口,发送数据前 比对 接收方发过来的即时窗口(滑动窗口),
TCP是面向连接的。连接管理就是三次握手与四次挥手的过程,保证可靠的连接。
发送的数据包的二进制相加然后取反,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP将丢弃这个报文段 和 不确认收到此报文段。
发送方:在发送数据之前计算检验和,并进行校验和的填充。
接收方:收到数据后,对数据以同样的方式进行计算,求出校验和,与发送方的进行比对。
注意:如果接收方比对校验和与发送方不一致,那么数据一定传输有误。但是如果接收方比对校验和与发送方一致,数据不一定传输成功。
补充:首部校验和。在TCP报文段首部中有16位的校验和字段,该字段用于校验整个TCP报文段(包括首部和数据部分)。IP数据报的首部校验和只对IP首部进行校验。TCP详细的校验过程如下,发送TCP报文段前求一个值放在校验位,接收端接受到数据后再求一个值,如果两次求值形同则说明传输过程中没有出错;如果两次求值不同,说明传输过程中发生错误,无条件丢弃该报文段引发超时重传。
序列号seq:TCP传输时将每个字节的数据都进行了编号,这就是序列号。
确认应答ack:每次接收方收到数据后,都会发送ack报文对发送方进行确认应答。这个ack报文当中带有对应的确认序列号,告诉发送方,接收到了哪些数据,下一次的数据从哪里发。
例如:上次A-》B:ack=6(希望下次发的数据编号为6),A《- B:seq =3 (当前发送的数据编号为3,但是ack希望发6,说明数据重复,则删除重复序号的数据)
在进行TCP传输时,由于确认应答与序列号机制,也就是说发送方发送一部分数据后,都会等待接收方发送的ACK报文,并解析ACK报文,判断数据是否传输成功。如果发送方发送完数据后,迟迟没有等到接收方的ACK报文,则采用超时重传机制进行重传。
(1)首先,发送方没有接收到响应的ACK报文原因可能有两点:
a、数据在发送过程中由于网络原因等直接全体丢包,接收方没有接收到。
b、接收方接收到了响应的数据,但是发送的ACK报文响应却由于网络原因丢包了。
(2)超时重传机制简单理解就是
发送方在发送完数据后等待一个时间,时间到达没有接收到ACK报文,那么对刚才发送的数据进行重新发送。
如果是刚才第一个原因,接收方收到二次重发的数据后,便进行ACK应答。
如果是第二个原因,接收方发现接收的数据已存在(判断存在的根据就是序列号,所以上面说序列号还有去除重复数据的作用),那么直接丢弃,仍旧发送ACK应答。
(3)那么发送方发送完毕后等待的时间是多少呢?
这个最大超时时间(也就是等待的时间)是动态计算的。
超时以500ms(0.5秒)为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。重发一次后,仍未响应,那么等待2*500ms的时间后,再次重传。等待4*500ms的时
间继续重传。以一个指数的形式增长。累计到一定的重传次数,TCP就认为网络或者对端出现异常,强制关闭连接。
(1)定义:
所谓流量控制,就是让发送端不要发送的过快,让接收端能来得及接收
问题:接收端在接收到数据后,对其进行处理。如果发送端的发送速度太快,导致接收端的接收缓冲区很快的填充满了。此时如果发送端仍旧发送数据,那么接下来发送的数据都会丢
包,继而导致丢包的一系列连锁反应,超时重传什么的,从而导致网络流量的无端浪费。
解决:所以TCP需要提供一种机制:让发送端根据接收端实际的接收能力控制发送的数据量。这就是所谓的流量控制。
(2)流量控制过程:
TCP 利用滑动窗口实现流量控制的机制, 而滑动窗口大小是通过TCP首部的窗口大小字段来通知对方。
滑动窗口大小的实际上是接收端接收数据缓冲区的剩余空间。这个数字越大,证明接收端接收缓冲区的剩余空间越大,网络的吞吐量越大。
流量控制的具体操作:
1)接收端会在确认应答时发送ACK报文时,将自己的即时窗口大小填入,并跟随ACK报文一起发送过去。(当接收端这个接收缓冲区面临数据溢出时,窗口大小的值就会随之设置成一个更小值,告诉发送端要控制一下发送的数据量了。)
2)而发送方根据ACK报文里的窗口大小的改变 进而改变自己的发送速度。(发送端接收到接收端的窗口变化指示后,就会对数据发送量进行调整)
3)如果接收端窗口大小的值为0,那么发送方将停止发送数据。并定期的向接收端发送窗口探测的数据段,让接收端把窗口大小告诉发送端。
等接收端处理完了缓冲区的数据后发送一个窗口更新的数据包通知,发送端才可以继续根据窗口大小发送数据。
(1)问题:
虽然有了滑动窗口机制,如果在通信刚开始的时候就发送大量的数据包,也有可能会导致网络的瘫痪。
(2)解决:
为了在发送端调节所要发送的数据量,定义了一个“拥塞窗口”cwnd(congestion window)。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。
发送窗口取拥塞窗口和接收端窗口的最小值,避免发送接收端窗口还大的数据。
(3)拥塞控制使用了两个重要的算法: 慢启动算法, 拥塞避免算法。
(4)拥塞控制的四种拥塞控制算法:
<1> 慢启动:
先发少量的数据探探路,看看当前网络的拥塞状态,再决定按照多大的速率进行传送,刚开始时,定义拥塞窗口的大小为1,
每当收到一个ACK,滑动窗口大小cwnd++; 呈线性上升
每当过了一个往返时延RTT,cwnd = cwnd*2; 呈指数上升,拥塞窗口值加倍(比如:2,4,8指数增长)
慢启动只是指初始时慢,但是增长速度很快,不久就可以造成网络拥塞。
引入一个慢启动的阈值ssthresh,当拥塞窗口cwnd >= 慢启动的阈值ssthresh的时候,就会进入“ 拥塞避免算法”
<2>拥塞避免:
当拥塞窗口cwnd >= 慢启动的阈值ssthresh时,窗口大小不再呈指数上升,而是以线性上升,避免增长过快导致网络拥塞。
每当收到一个ACK,cwnd = cwnd + 1/cwnd
每当过了一个RTT,cwnd = cwnd + 1
拥塞发生:当发生丢包进行数据包重传时,表示网络已经拥塞。分两种情况进行处理:
等到RTO超时,重传数据包;
sshthresh = cwnd /2
cwnd 重置为 1 ,进入慢启动过程 ;
快重传和快恢复是为了进一步改进拥塞控制
<3>快速重传:
问题:有时个别报文段会在网络中丢失,但实际上网络并未发生拥塞。
解决:使用快速重传
如图所示,
报文段1:发送端A 将报文段1发送到接收端B,B向A发送确认字段ACK2(发送成功)
报文段2:发送端A在发送报文段2的过程中,出现丢包问题(发送失败)
报文段3:接着发送端A将报文段3发送到接收端B,B发现报文段未按序到达(tcp应该按序处理,未处理报文段2,没办法处理其后面的报文段)
因此,接收端B接收到报文段3、4、5后,仍然发送的是针对报文段1的确认字段ACK2(连续发了三次)
接收到连续的三个重复冗余ACK2,于是重发报文段2,不需要等待超时重传定时器溢出
总结:
如果在超时重传定时器溢出之前,接收到连续的三个重复冗余ACK(其实是收到4个同样的ACK,第一个是正常的,后三个才是冗余的),
发送端便知晓哪个报文段在传输过程中丢失了,于是重发该报文段,不需要等待超时重传定时器溢出,大大提高了效率。这便是快速重传机制。
<4>快恢复(与快重传配合使用):
(5)拥塞控制的流程:
<1>TCP加入慢启动算法,先发少量的数据探探路,看看当前网络的拥塞状态,再决定按照多大的速率进行传送,刚开始时,定义拥塞窗口的大小为1,每当过了一个往返时延RTT,
cwnd = cwnd*2; 呈指数上升,拥塞窗口值加倍(比如:2,4,8指数增长),这样的拥塞窗口增长的速度是指数级别的,慢启动只是指初始时慢,但是增长速度很快,不久就可以造成
网络拥塞。为了不让窗口一直加倍增长,我们引入一个慢启动的阈值ssthresh,当拥塞窗口超过这个阈值的时候,就会进入“ 拥塞避免算法”,而是按照线性方式增长。
<2> 拥塞避免算法每次过了一个往返时延RTT,拥塞窗口的值加1(加法增大),如果发现出现网络拥塞(没有按时收到确认ack)的话就按照上面的方法重新设置慢启动的阈值
ssthresh的大小(乘法减小,原来的二分之一)并从拥塞窗口cwnd=1开始重新执行慢启动算法。
<3> 如果遇到3个重复确认,则使用快速重传算法,重传丢失的个别报文
<4> 由于只是丢失个别报文,不使用满启动算法,而是使用快速恢复算法,即将慢启动的阈值ssthresh和拥塞窗口大小cwnd设置为当前cwnd的一半,执行拥塞避免算法
慢启动的阈值ssthresh的作用是:
注意:RTT(Round-Trip Time) 指往返时延,表示从发送端发送数据开始,到发送端收到来自接收端的确认(来回),总共经历的时延。
(6)下图拥塞控制的流程示例:
流量控制 是作用于接收者的,它是控制发送者的发送速度从而使接收者来得及接收,防止丢失数据包的
拥塞控制 拥塞控制是作用于网络的,它是防止过多的数据注入到网络中,避免出现网络负载过大的情况
拥塞控制是一个全局性的过程,和流量控制不同,流量控制指点对点通信量的控制
为了防止已失效的连接请求报文段突然又传送到了服务端,服务器端一直等待而浪费资源,因而产生错误。
(进行三次握手的原因补充:
第一,为了确认双方的接收与发送能力是否正常。
第二,指定自己的初始化序列号,为后面的可靠传送做准备。
第三,如果是 https 协议的话,三次握手这个过程,还会进行数字证书的验证以及加密密钥的生成到。
)
如果此时客户端发送的延迟的握手信息服务器收到,然后服务器进行响应,认为客户端要和它建立连接,此时客户端并没有这个意思,但 server
却以为新的运输连接已经建立,并一直
等待 client
发来数据。这样,server
的很多资源就白白浪费掉了。
具体例子:“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个
时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意
建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数
据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,
client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”
定义:SYN- Flood攻击是当前网络上最为常见的DDoS攻击,也是最为经典的拒绝服务攻击。
它就是利用了TCP协议实现上的一个缺陷,通过向服务器发送大量 的伪造ip的攻击报文,就可能造成目标服务器中的半开连接队列(上文所说的未连接队列,即server收到
连接请求SYN之后将client加入半连接队列中)被占满,从而使得server拒绝其他正常的连接请求。即拒绝服务攻击。而且由于它可以方便地伪造源地址,追查起来非常困难。
原理:攻击者首先伪造IP地址对 服务器发起SYN请求,服务器回应(SYN+ACK)包,而真实的IP会认为,我没有发送请求,不作回应。服务器没有收到回应,这样的话,服务器不知道
(SYN+ACK)是否发送成功,默认情况下会重试5次(tcp_syn_retries)。这样的话,对于服务器的内存,带宽都有很大的消耗。攻击者 如果处于公网,可以伪造IP的话,对于服务器就很
难根据IP来判断攻击者,给防护带来很大的困难。
(1)方法一:缩短服务器 接收客户端SYN报文之后的等待连接时间,即SYN timeout时间,也就是server接收到SYN报文段,到最后放弃此连接请求的超时时间,
将SYN timeout设置的更低,便可以成倍的减少server的负荷,但是过低的SYN timeout可能会影响正常的TCP连接的建立,一旦网络不通畅便可能导致client连接请求失败
(2)方法二:SYN cookie + SYN proxy 无缝集成(较好的解决方案)
SYN cookie:当server接收到client的SYN之后,不立即分配资源,而是根据client发送过来的SYN包计算出一个cookie值,这个cookie值用来存储server返回给client的SYN+ACK数据包
中的初始序列号,当client返回第三次握手的ACK包之后进行校验,如果校验成功则server分配资源,建立连接。
SYN proxy代理:作为server与client连接的代理,代替server与client建立三次握手的连接,同时SYN proxy与client建立好了三次握手连接之后,确保是正常的TCP连接,而不是TCP泛
洪攻击,那么SYN proxy就与server建立三次握手连接,作为代理(网关?)来连通client与server。(类似VPN了解一下。)
当client与server的第三次握手失败了之后,即client发送至server的确认建立连接报文段 未能到达server,server在等待client回复ACK的过程中超时了,那么server会向client发送一个
RTS复位报文段 并进入关闭状态,即:并不等待client第三次握手的ACK包重传,直接关闭连接请求,这主要是为了防止SYN泛洪攻击,即坏人伪造许多IP向server发送连接请求,从而
将server的未连接队列塞满,浪费server的资源。
注:MSS(Maximum Segment Size),最大报文长度,是TCP用来限制应用层最大的发送字节数。
TCP和UDP,首先要明白“连接”和“无连接”的含义,他们的关系可以用一个形象地比喻来说明,就是打电话和写信。两个人如果要通话,首先 要建立连接——即打电话时的拨号,等待响应后——即接听电话后,才能相互传递信息,最后还要断开连接——即挂电话。写信就比较简单了,填写好收信人的地址 后将信投入邮筒,收信人就可以收到了。
(可能不对:本次连接产生,接收端会发送确认ack;延迟的报文将丢弃,不发送ack)
HTTP(HTTP,HyperText Transfer Protocol)超文本传输协议
HTTP协议是HTTP就是负责在客户端请求资源,在服务器端响应的协议、是一个基于请求与响应,无状态的,应用层的协议,常基于TCP/IP协议传输数据。所有的WWW文件都必须遵守这个标准。
(1)HTTP报文:HTTP协议在客户端和服务端之间传送的数据块。
(2)在TCP/IP协议栈中的位置:HTTP协议通常承载于TCP协议之上,有时也承载于TLS或SSL协议层之上(这个时候,就成了我们常说的HTTPS),默认HTTP的端口号为80,
HTTPS的端口号为443。如下图所示:
(3)无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
但是现在的应用都是有状态的,如果是无状态,那这些应用基本没人用,你想想,访问一个 电商网站,先登录,然后去选购商品,当点击一个商品加入购物车以后又提示你登录。这种 用户体验根本不会有人去使用。
(4)那我们是如何实现带状态的协议呢?:客户端支持的 cookie
Http 协议中引入了 cookie 技术,用来解决 http 协议无状态的问题。通过在请求和响应报文 中写入 Cookie 信息来控制客户端的状态;Cookie 会根据从服务器端发送的响应报文内的一 个叫做 Set-Cookie 的首部字段信息,通知客户端保存 Cookie。当下次客户端再往该服务器 发送请求时,客户端会自动在请求报文中加入 Cookie 值后发送出去。
一次HTTP操作称为一个事务,其工作过程可分为四步:
1)首先浏览器与服务器需要建立连接。
2)建立连接后,浏览器向服务器发送请求命令(请求行,例如:POST /chapter17/user.html HTTP/1.1)
浏览器向服务器发送请求头信息,最后发送一个空请求头,代表请求头信息发送完毕
如果是post请求,会继续提交请求体
3)服务器接到请求后,服务器应答,向浏览器发送响应行(例如:HTTP/1.1 200 OK)
服务器向浏览器发送响应头信息,最后发送一个空白行,表示响应头信息发送完毕
服务器向浏览器发送响应体信息,根据响应头中 Content-Type所描述的格式,发送用户所请求的实际数据
4)客户端接收服务器所返回的信息,通过浏览器显示在用户的显示屏上,然后客户机与服务器断开连接。
如果在以上过程中的某一步出现错误,那么产生错误的信息将返回到客户端,由显示屏输出。对于用户来说,这些过程是由HTTP自己完成的,用户只要用鼠标点击,等待信息显示就可以了。
HTTP请求报文由3部分组成:请求行 + 请求头 + 请求体
第一部分:请求行,用来说明请求类型,要访问的资源以及所使用的HTTP版本.
第二部分:请求头,紧接着请求行(即第一行)之后的部分,用来说明服务器要使用的附加信息
第三部分:空行,请求头部后面的空行是必须的(即使第四部分的请求数据为空,也必须有空行)
第四部分:请求体(也叫请求数据),当请求方式是post的时,请求体 会有请求的参数。
格式:请求方式 资源路径 协议/版本 (例如:POST /chapter17/user.html HTTP/1.1)
请求行必须在http请求格式的第一行。
HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法。
HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法
最常的两种GET和POST
(1)GET: 请求指定的页面信息(安全性、长度限制、请求内容的位置)
(2)POST: 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
(3)HEAD:类似于get方法,只不过返回的响应中没有具体的内容,用于获取报头(即不返回响应体)
(4)OPTIONS: 允许客户查看服务器的性能
(5)PUT: 向指定资源位置上传其最新内容
(6)DELETE: 请求服务器删除指定的页面
(7)TRACE:回显服务器收到的请求,主要用于测试或诊断
(8)CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
注意:方法名称是区分大小写的;
HTTP服务器至少应该实现GET和HEAD/POST方法,其他方法都是可选的;
URL:统一资源定位符,是一种自愿位置的抽象唯一识别方法。
组成:<协议>://<主机>:<端口>/<路径>
端口和路径有时可以省略(HTTP默认端口号是80)
如下例(GET请求会带参数):
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Http缓存主要涉及三个角色:一是浏览器,二是浏览器的缓存数据库,三是服务器。
Http缓存主要分为两种:强缓存(适合请求不变的内容,例如图片,直接从缓存中获取) 和协商缓存(适合请求变化的内容)。两种缓存分别通过Http报文头部不同的字段进行控制
(1)浏览器第一次加载资源,向服务器发送请求,服务器返回数据和缓存规则(200),然后将数据缓存到缓存数据库。
(返回的响应头中有文件内容标记etag
和文件最后修改时间last-modified字段,将其保存到浏览器请求头的字段
If-None-Match和 If-Modified-Since中,并在下一次向服务器发送请求时发送)
(2)下一次加载资源时,查看Cache-Control:max-age,判断缓存的内容是否过期,如果没有过期,则使用强缓存的方式,使用缓存数据库中的数据(200)。
(3)如果缓存内容过期,则使用协商缓存的方式,向服务器带有发送请求,请求中有If-None-Match和 If-Modified-Since字段(即上次保存的文件内容标记etag
和文件最后修改时间last-modified
)
(4)服务器收到请求后,先判断被请求的文件内容是否改变(即比较文件内容标记If-None-Match和当前服务器中的文件内容标记etag
),如果没有改变(返回304),则直接从缓存数据库中获取数据。如果内容发生改变,服务器直接返回数据和当前的etag、last-modified字段(返回200),将获取的数据缓存。(
Etag优先级 大于 Last-Modified,故先判断内容)
(5)如果请求字段中没有文件内容标记If-None-Match,判断文件最后修改时间是否一致(即比较文件内容标记If-Modified-Since和当前服务器中的文件内容标记last-modified
),如果一致(返回304),则直接从缓存数据库中获取数据。如果不一致,服务器直接返回数据和当前的etag、last-modified字段(返回200),将获取的数据缓存。
请求头中:
响应头中:
Etag优先级 大于 Last-Modified
强缓存基本原理是:所请求的数据在缓存数据库中尚未过期时,不与服务器进行交互,直接使用缓存数据库中的数据。关注时间,返回200(请求被正常处理)
控制强缓存过期时间的主要有两个规则字段:
Expire (在响应头中,旧的方式):其指定了一个时间, 在这个时间之后,HTTP响应被认为是过时的(-1或0代表不缓存)。
但是它本身是一个HTTP1.0标准下的字段,所以如果请求头中有Cache-Control属性设置了 “max-age” 或者 “s-max-age” ,那么 Expires 头就会被忽略。
Cache-Control(在响应头和请求头中,新的方式):通用消息头用于在http 请求和响应中通过指定指令来实现缓存机制。其常用的几个取值有:
请求头里的Cache-Control是no-cache 是浏览器通知服务器:本地没有缓存数据
响应头中的 Cache-Control:max-age=259200 是通知浏览器:259200 秒之内别来烦我,自己从缓冲区中刷新
例如·:缓存可以被客户端和代理服务器缓存(public),并且缓存的时间为315…秒(365天)后失效。在其缓存过期时间之内,所以直接命中并从磁盘中读取,不需要与服务器交互。
当强缓存过期未命中或者响应报文
Cache-Control
中有must-revalidate
标识必须每次请求验证资源的状态时,便使用协商缓存的方式去处理缓存文件。关注的是文件内容是否变化,返回304、
Ctrl+F5强制刷新,no-cache:没有缓存,直接进行协商缓存(不执行强缓存)
请求头中:
If-Modified-Since:如果请求的部分在指定时间之后被修改则请求成功。(If-Modified-Since: Mon, 16 Mar 2020 11:11:11 GMT)
浏览器先请求服务获得文件后,服务器会返回该文件的最后修改时间Last-Modified
,作为文件的一个标识,下次浏览器请求的时候,会带着这个标识去请求(此时为If-Modified-Since
)
如果说时间标识If-Modified-Since
等于服务器的文件修改时间,则说明没有修改,返回304状态码,浏览器从缓存中获取文件;
如果说时间标识If-Modified-Since
的时间如果大于服务器端文件的时间,会被认为是错误的请求;
如果浏览器保存的时间标识If-Modified-Since
小于服务器端的文件修改时间,说明文件发生了修改,浏览器就会重新获取新的文件,并缓存到浏览器中。
If-None-Match:只有请求内容与实体不匹配才获取该数据。(If-None-Match: “306073f04224cbd114f14693c272f6a0”)
可能存在一个问题:就是有可能服务器端的文件修改后,没有文件改变内容,这样,虽然文件最后修改时间变了,但是,文件内容并没有改变。
服务器端先比较文件内容是否一致,
如果一致,则证明文件内容没变化,返回304状态码,让浏览器从缓存中拿取文件。
如果内容不一致,则证明文件修改了,需要浏览器重新下载文件。
响应头中:
ETag:请求变量的实体标签的当前值(取得是文件内容的MD5值,文件内容没变化,ETag值也不会变)。(ETag: “306073f04224cbd114f14693c272f6a0”)
Last-Modified:请求资源的最后修改时间 (Last-Modified: Mon, 16 Mar 2020 11:11:11 GMT)
HTTPS是一种通过计算机网络进行安全通信的传输协议,基于HTTP协议,通过SSL或TLS提供加密处理数据、验证对方身份以及数据完整性保护。
PS:TLS是传输层加密协议,前身是SSL协议,由网景公司1995年发布,有时候两者不区分。
HTTPS有如下特点:
- 内容加密:采用混合加密技术,中间者无法直接查看明文内容
- 验证身份:通过证书认证客户端访问的是自己的服务器
- 保护数据完整性:防止传输的内容被中间人冒充或者篡改
- 接收方能够证实发送方的真实身份;
- 发送方事后不能否认所发送过的报文;
- 接收方或非法者不能伪造、篡改报文。
使用到了三种技术:对称加密+非对称加密+数字证书
服务器端:生成公钥和私钥(非对称),
客户端:生成私钥(对称)
非对称+对称加密的过程:
服务器端先将公钥给客户端,便于客户端用公钥对其生成的私钥进行加密,
客户端用公钥对其生成的私钥加密,发送给服务器端
服务器端获得私钥后,客户端使用私钥对内容进行对称加密,服务器通过私钥解密数据
问题:服务器将私钥发送给客户端的过程中,可能会被黑客拦截,黑客将伪造的公钥和私钥对,将它的公钥发给用户
解决:数字证书
重点是第二个步骤,SSL安全参数握手,我们从这里面可以看到,经历了第二个过程,就可以实现加密和解密了。
如下是SSL安全参数握手的过程
(1)客户端,首先生成一个随机数1,然后再把随机数、支持的协议版本(SSL版本)以及它所支持的加密算法告诉服务端,这时候数据是明文的,不加密的。
(2)服务器,也会生成一个随机数2,然后提供自己的数字证书,确定客户端的加密算法(客户端支持的加密算法中的算法)。
服务端必须要有一套数字证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面,这套证书其实就是一对公钥和私钥。传送的证书,包含公钥,只是包含了很多信息,如证书的颁发机构,过期时间、服务端的公钥,第三方证书认证机构(CA)的签名,服务端的域名信息等内容。
(3)客户端解析证书,首先确认证书是否有效,如果无效,则认为服务器是不安全的。如果有效,生成随机数3,并使用证书里面提供的公钥加密随机数3。然后把加密之后的数据发送给服务端。此时客户端和服务器都拥有了随机数1,2,3.
此时只有服务器自身才可以把随机数3解密,其他人就无法界面了。
(4)此时双方的信息对称,都拥有随机数1,2,3,然后根据随机数1,2,3,和相同的算法生成对称密钥,生成对称密钥之后就可以进行加密的传输了。
(5)客户端通过会话秘钥加密一条消息发送给服务端,主要验证服务端是否正常接受客户端加密的消息。
(6)同样,服务端也会通过会话秘钥加密一条消息回传给客户端,如果客户端能够正常接受的话表明SSL层连接建立完成了。
HTTPS综合使用对称加密和非对称加密
双方分别生成秘钥,没有经过传输,减少了密钥泄露的可能。
(1)数字证书
是可信任组织颁发给特定对象的认证
数字证书的内容:
数字证书中包含了对象的公开密钥。
(2)SSL(Secure Sockets Layer:安全套阶层)
SSL层是位于传输层和应用层之间,它是一个子层,提供数据安全和数据完整的服务,以及对传输层数据进行加密后传输。数据安全,保证数据不会被泄露,数据完整指的是数据在传输的过程中,不会被篡改。
(1)端口 :HTTP的URL由“http://”起始,且默认使用端口80,而HTTPS的URL由“https://”起始,且默认使用端口443。
(2)安全性: HTTP协议运行在TCP之上,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。HTTPS是运行在SSL/TLS之上的HTTP协议,SSL/TLS 运行在TCP之上。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。所以说,HTTP 安全性没有 HTTPS高。
(3)资源消耗:HTTPS 比HTTP耗费更多服务器资源;SSL证书需要购买申请,功能越强大的证书费用越高
HTTP的响应报文也由三部分组成(响应行+响应头+响应体)
第一部分:响应行,由HTTP协议版本号, 状态码, 状态消息 三部分组成。下图表明 :HTTP版本为1.1版本,状态码为200,状态消息为(ok)
第二部分:响应头,用来说明客户端要使用的一些附加信息,服务器通过响应头来控制浏览器的行为
第三部分:空行,响应头后面的空行是必须的
第四部分:响应体,服务器返回给客户端的文本信息。服务器回写给客户端的页面正文,浏览器将正文加载到内存,然后解析渲染 ,显示页面内容
(1)HTTP/1.0:默认使用的是短连接,也就是说每次请求都要重新建立一次连接。HTTP 是基于TCP/IP协议的,每一次建立或者断开连接都需要三次握手四次挥手的开销,如果每次请
求都要这样的话,开销会比较大。因此最好能维持一个长连接,可以用个长连接来发多个请求。
(2)HTTP 1.1:默认使用长连接, 默认开启Connection: keep-alive。 HTTP/1.1的持续连接有非流水线方式和流水线方式 。流水线方式是客户在收到HTTP的响应报文之前就能接着
发送新的请求报文。与之相对应的非流水线方式是客户在收到前一个响应后才能发送下一个请求。
- 1xx:信息提示,表示请求已接收,继续处理
- 2xx:成功,表示请求已被成功接受,处理。
- 3xx:重定向,要完成请求必须进行更进一步的操作
- 4xx:客户端错误,请求有语法错误或请求无法实现
- 5xx:服务器端错误,服务器未能实现合法的请求。
常考的状态码:
200:请求被正常处理
204:请求被受理但没有资源可以返回
206:客户端只是请求资源的一部分,服务器只对请求的部分资源执行GET方法,相应报文中通过Content-Range指定范围的资源。
301:永久性重定向
302:临时重定向
303:与302状态码有相似功能,只是它希望客户端在请求一个URI的时候,能通过GET方法重定向到另一个URI上
304:发送附带条件的请求时,条件不满足时返回,与重定向无关
307:临时重定向,与302类似,只是强制要求使用POST方法
400:请求报文语法有误,服务器无法识别
401:请求需要认证
403:请求的对应资源禁止被访问
404:服务器无法找到对应资源
500:服务器内部错误
503:服务器正忙
301和302的相等点与不同点:
什么时候进行301或者302跳转呢?
使用302跳转的场景,尽量使用301跳转!
- 解析HTML,生成DOM树:渲染引擎解析HTML文档,首先将标签转换成DOM node(包括js生成的标签)生成DOM 树;
- 解析CSS,生成CSSOM树;
- 将DOM树和CSSOM树结合,生成渲染树(Render Tree)。渲染并不等同于 DOM 树,渲染树中的每一个节点都有自己的style,而且不包含隐藏的结点(像 head结点 或 display:none 的结点),这些节点不会用于呈现;
- 布局渲染树:从根节点递归调用,计算每一个元素的大小、位置等,给出每个节点应该在屏幕上出现的精确坐标;
- 绘制渲染树:遍历渲染树,使用UI层来绘制每个节点。
- Reflow(回流,又叫重排): 浏览器要花时间去渲染,当它发现了某个部分发生了变化影响了布局(尺寸、布局、隐藏等改变会影响布局),那就需要倒回去重新渲染。
- Repaint(重绘): 如果只是改变了某个元素的背景颜色,文字颜色等,不影响元素周围或内部布局的属性,将只会引起浏览器的重绘,重画某一部分。(Reflow要比Repaint更花费时间,也就更影响性能)
- Display:将像素发送给GPU,展示在页面上。(这一步其实还有很多内容,比如会在GPU将多个合成层合并为同一个层,并展示在页面中。而css3硬件加速的原理则是新建合成层)
(1)在构建DOM时,HTML解析器若遇到了JavaScript,那么它会暂停构建DOM,将控制权移交给JavaScript引擎,等JavaScript引擎运行完毕,浏览器再从中断的地方恢复DOM构
建。(因为JavaScript可以修改网页的内容,它可以更改DOM,如果不阻塞,那么这边在构建DOM,那边JavaScript在改DOM,如何保障最终得到的DOM是否正确?而且在JS中前一秒
获取到的DOM和后一秒获取到的DOM不一样,它会产生一系列问题,所以JS是阻塞的,它会阻塞DOM的构建流程。)
(2)在构建DOM时,若遇见CSS会立刻构建CSSOM,它们可以同时进行,CSSOM树的构建不会阻塞构建过程,但是会阻塞渲染(哪怕DOM已经构建完,必须等CSSOM构建完毕才能
进入渲染阶段,因为JavaScript不只是可以改DOM,它还可以更改样式,也就是它可以更改CSSOM)。
(3)JavaScript对关键渲染路径的影响不只是阻塞DOM的构建,它会导致CSSOM也阻塞DOM的构建。原本DOM和CSSOM的构建是互不影响,并行构建的,引入了JavaScript后,阻
塞了DOM的构建,但由于JavaScript可以修改CSSOM,所以需要等CSSOM构建完毕后再执行JS。等js运行完毕后,再从中断的地方恢复DOM构建。
(4)为了更好的用户体验,渲染引擎将会尽可能早的将内容呈现到屏幕上,并不会等到所有的html都解析完成之后再去构建和布局render树。它是解析完一部分内容就显示一部分内
容,同时,可能还在通过网络下载其余内容。
(5)在构建DOM的过程中,如果遇到外联的样式声明或脚本声明,则暂停文档解析,创建新的网络连接,开始下载样式文件和脚本文件。样式文件下载完成后,构建CSS Rule DOM,
脚本文件下载完成后,解释并立即执行。
(1)将css放在头部是为了减小浏览器的重绘成本,
(2)将js放在末尾的原因主要有两个:1.确保能取到需要操作的dom对象;2:缩短因为js的阻塞而造成的白屏时间,提升用户体验。
(1)回流(重排):当render树中的一部分或者全部因为大小边距等问题发生改变而需要重建的过程叫做回流(改变大小)。
(2)重绘:当元素的一部分属性发生变化,如外观背景色不会引起布局变化而需要重新渲染的过程叫做重绘(改变样式)。
注意:回流必将引起重绘(div的位置发生变化,会导致其它部分受影响,并重新构造这部分的渲染树,完成回流;浏览器再重新绘制受影响的部分到屏幕中,完成重绘);
重绘不一定会引起回流(颜色改变不会影响布局变化)。
(1)回流发生条件
(2)重绘发生条件:元素的属性或者样式发生变化。
(3)回流的开销较大,如果每个操作都去回流重绘的话,浏览器可能就会受不了。所以很多浏览器都会优化这些操作,浏览器会维护1个队列,把所有会引起回流、重绘的操作放入这个队列,等队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器就会进行一个批处理。这样就会让多次的回流、重绘变成一次回流重绘。
虽然有了浏览器的优化,但有时一些代码可能会强制浏览器提前处理,这样浏览器的优化可能就起不到作用了。当请求向浏览器请求一些 style信息的时候,就会让浏览器flush(输出)队列,比如:
(1)offsetTop, offsetLeft, offsetWidth, offsetHeight
(2) scrollTop/Left/Width/Height
(3)clientTop/Left/Width/Height
(4)width,height
(5)请求了getComputedStyle(), 或者 IE的 currentStyle
减少回流和重绘其实就是需要减少对render tree的操作,并减少对一些样式信息的请求,尽量利用好浏览器的优化策略。
(1)让元素脱离文档流
什么是脱离文档流:
使DOM脱离文档流的方式:
(2)将需要多次重排的元素(有动画效果的元素),position属性设为absolute或fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。
(3)通过合并多次DOM样式的修改,来减少回流和重绘的发生次数。
(4)避免逐项改变样式,最好一次性改变样式属性。或者将样式定义成class进行一次性修改
(5)添加css样式而不是利用js控制样式(我就是想到这种办法解决回流问题的)
(6)尽量不要使用表格布局。
(7)使用css3硬件加速,可以让transform、opacity、filters
等动画效果不会引起回流重绘
(8)不要经常访问会引起浏览器flush队列的属性,如果你确实要访问,利用缓存
(9)如果需要创建多个DOM节点,可以创建完后使用DocumentFragment 一次性加入document。(不会创建一次加一次,而是创建完一次性加入)
为了防止脚本加载使浏览器页面阻塞,妨碍用户体验。应该合理使用<script>标签的defer属性和async属性。这两个属性用于调整脚本的下载和执行顺序,使其不阻塞页面加载。
(1)defer:开启新的线程下载脚本文件,并使脚本在文档解析完成后执行。
(2)async:异步下载脚本文件,下载完毕立即解释执行代码。 HTML5的新增属性。
- 第一次挥手:主动关闭方向被动关闭方发送结束报文段。
- 第二次挥手:被动关闭方发送结束报文段确认,此时主动关闭方数据已经传输完毕。
- 第三次挥手:被动关闭方数据也发送完毕,发送结束报文段。
- 第四次挥手:主动关闭方对结束报文段进行确认。
(1)第一次挥手:客户端进程发出连接释放报文,并且停止发送数据。客户端进入FIN-WAIT-1(终止等待1)状态。如果服务端有数据要发给客户端,客户端照样可以接收的。此时客户端处于FIN = 1等待服务端确认释放连接状态。TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。(FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1))
(2)第二次挥手:服务器收到连接释放报文,发出确认报文。服务端就进入了CLOSE-WAIT(等待关闭)状态。客户端向服务器方向的连接就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。(ACK=1,ack=u+1,并且带上自己的序列号seq=v)。
客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
(3)第三次挥手:服务器将最后的数据发送到客户端,并发送FIN = 1连接释放报文。用于告诉客户端,服务端的所有数据发送完毕,客户端你也可以关闭接受数据连接了。服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
(4)第四次挥手:客户端收到服务器的连接释放报文后,发出确认,ACK=1。此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,服务器只有收到了客户端发出的确认,才进入CLOSED状态。
虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发第四次挥手时
可能丢失的ACK报文。在客户端发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以不能立即关闭,它必须确认Server接收到了该
ACK。客户端会在发送出ACK之后进入到TIME_WAIT状态,会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么客户端会重发ACK并再次等待2MSL。所
谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,客户端都没有再次
收到FIN,那么客户端推断ACK已经被成功接收,则结束TCP连接。
(1)在TCP三次握手中,当服务器端收到客户端端的连接请求报文后(第二次握手),可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。
(2)在TCP四次挥手关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭连接,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我
Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
TCP还设有一个保活计时器。如果一方出现问题,另一方过了这个计时器的时间,就发送试探报文,以后每隔 75 秒发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户
端出了故障,接着就关闭连接。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。