一、浏览器
1、浏览器缓存
浏览器缓存是浏览器在本地磁盘对用户最近请求过得文档进行存储,当访问者再次访问同一页面时,浏览器就可以直接从本地磁盘加载文档。
浏览器缓存主要分为强缓存(也称本地缓存)和协商缓存(也称弱缓存)
优点:1、减少冗余的数据传输 2、减少服务器负担 3、加快客户端加载网页速度
浏览器缓存是web性能优化的重要方式
浏览器第一次发起请求
浏览器第一次发起请求时,本地无缓存,向web服务器发送请求,服务器响应请求,浏览器缓存。
这个过程中,服务器会将资源的更新时间通过Last-Modified标识发送给客户端;还会再发送一个Etag
(注:第一次请求肯定是协商缓存)
浏览器再次发送请求
1、第一种情况:先获取本地缓存资源的header信息,根据header中的Cache-Contro 和Expires判断是否过期。
没有过期,则不向浏览器请求,直接从缓存中获取资源。(强缓存相关)
2、第二种情况:资源显示过期,浏览器向服务器发送请求
A.与服务器对比Etag,相同,返回304,客户端继续使用本地缓存,不解析服务器发回的数据。不同则返回200
B.对比两者的Last-Modified(更新时间),相同则返回304,客户端继续使用本地缓存。不同返回200
2、强缓存和协商缓存
缓存分成两种:强缓存和协商缓存,根据响应的header内容来决定
最直接区别:
1、强缓存:直接使用本地的缓存,不用跟服务器进行通信
2、协商缓存:将资源一些相关信息返回服务器,让服务器判断浏览器是否能直接使用本地缓存,整个过程至少与服务器通信一次
| 类别 | 获取自资源形式 | 状态码 | 是否发送请求到服务器 |
|---|---|---|---|
| 强缓存 | 从缓存取 | 否,直接从缓存取 | |
| 协商缓存 | 从缓存取 | 304(not modified) | 是,通过服务器来告知缓存是否可用 |
强缓存相关字段:expires、cache-control。同时存在时,cache-control > expires
协商缓存相关字段:Last-Modified / if-Modified-Since , Etag/if-None-Match
3、cookie和session
为什么要有cookie和session?
HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。服务器无法跟踪上一次的会话
cookie
Cookie,类型为“小型文本文件”,某些网站为了辨别用户身份而存在用户本地的数据。浏览器会在特定的情况下携带上cookie来发送请求,可以通过cookie来获取一些信息。
1、cookie数据保存在客户浏览器上,而session数据放在服务器上
2、cookie是明文存储的,不是很安全。
3、单个cookie保存的数据不能超过4k,很多浏览器都限制一个站点最多保存20个cookies
4、cookie分为内存cookie(会话cookie)和硬盘cookie,内存cookie保存在内存中,在浏览器关闭时会消失。硬盘cookie保存在硬盘中,过期时才会删除。
5、cookie是以文本的方式保存在客户端,每次请求时都带上它,消耗带宽
session
session是基于cookie实现其机制
1、session数据存放在服务器上
2、session可以以密文形式存储cookie,考虑到安全应当使用session
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用服务器的性能
现在用的最多的是token
cookie和session的缺点
1、cookie会附加在每个http请求中,增加了用户流量
2、cookie是明文传递的,存在安全性问题
3、cookie的大小限制是4kb,对复杂的需求来说是不够的
4、对于浏览器外的其他客户端(IOS、android),需要手动设置cookie和session
5、对于分布式系统和服务器集群,难以保证其他系统也可以正确解析session
4、token
什么是token?
token也可以翻译成令牌,就是在验证用户账号密码正确的情况下,给用户颁发一个令牌,这个令牌作为后续用户访问一些接口或者资源的凭证,服务器会根据这个凭证来判断用户是否有权限来访问。
具体可分为两步:
1、生成token:登录的时候,颁发token
2、验证token:访问某些资源或者接口时,验证token
JWT实现tkoen
token:header+payload+signature
jwt生成的token由三部分组成:
1、header
会通过base64Url算法进行编码
参数alg:采用的加密算法,默认是HMAC SHA256,采用同一密钥进行加密解密
参数typ:JWT,固定值,通常写成JWT
2、payload
表示携带的数据,会通过base64Url算法进行编码
可以携带用户的id,name,过期时间等信息,默认携带iat令牌的签发时间
3、signature
signature会将前两个结果合并进行HS256的算法(相当于加密)
5、Web Storage
在HTML5中,重新提供了一种在客户端本地保存数据的功能,它就是Web Storage。
Web Stotage存储机制是对html4中cookie存储机制的改善
分类
1、localStorage(本地存储)
将数据保存在客户端本地的硬件设备(通常是硬盘),即时浏览器关闭了,该数据仍然存在,下次打开浏览器访问网站时仍然可以继续使用
2、sessionStorage(会话储存)
将数据保存在session对象中。所谓session,是指用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览这个网站所花费的时间。session对象可以用来保存在这段时间内所要求保存的任何数据。
主要区别:localStorage为永久保存,sessionStorage是临时保存
| 特性 | cookie | sessionStorage | localStorage |
|---|---|---|---|
| 数据生命周期 | 生成时指定的maxAge值,就是cookie的生命周期 | 页面会话期间可用,页面关闭即清除 | 除非数据被清除,否则一直存在 |
| 存放数据大小 | 4k左右(并且每次http请求都会携带cookie) | 5M | 5M |
| 与服务器通信 | 由服务器的请求来传递,每次都会携带在http头中,使用cookie保存过多数据会带来性能问题 | 不参与和服务器通信 | 不参与和服务器通信 |
| 易用性 | cookie需要自己封装setCookie、getCookie | 直接使用原生接口 | 直接使用原生接口 |
注:sessionStorage在关闭了浏览器窗口就会被销毁。同时独立打开同一窗口同一个页面,sessionStorage也是不一样的
基本使用
// 设置sessionStorage
sessionStorage.setItem('name','linming')
sessionStorage.setItem('password','123123')
// 读取
let name = sessionStorage.getItem('name')
let password = sessionStorage.getItem('password')
console.log(name,password);
// 设置localStorage
localStorage.setItem('name','linming')
localStorage.setItem('password','123123')
// 获取
const name = localStorage.getItem('name')
const password = localStorage.getItem('password')
console.log(name,password);
6、回流与重绘
回流(reflow)
当render tree中的一部分(或全部)因为元素的尺寸、布局、隐藏等改变而需要重新构建,就称为回流。
注:每个页面至少需要一次回流,就是在页面第一次加载的时候
重绘(repaint)
当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观、风格、而不会影响布局的,比如color、background-color等,就称为重绘
区别
1、引起DOM树结构变化,页面布局变化的行为就是回流
2、只式样式的变化,不会引起DOM树变化、页面布局变化的行为叫重绘
3、回流必将引起重绘,而重绘不一定会引起回流
4、回流的代价要远远大于重绘
如何减少回流
1、减少对DOM的增删行为
比如删除某个节点、给某个父元素添加子元素
2、减少几何属性的变化
比如元素的宽高变化、border变化、字体大小变化
(可以将这些变化放在一个class中,直接添加class,这样就只引起一次回流)
3、减少元素位置的变化
比如修改一个元素的margin、padidng
(可以脱离文档流的改变位置会更好)
4、减少获取元素的偏移量属性
例如获取一个元素的scrollTop、scrollLeft等属性,浏览器为了保证值的正确也会回流取得最新的值
5、页面的初次渲染
无法避免
6、浏览器窗口尺寸变化
resize事件也会引起回流
二、计算机网络
1、 OSI七层模型
开放式系统互联模型
从上到下:
应用层:文件传输、常用协议HTPP、FTP
定义了网络主机提供的方法和接口,往往直接对应用户行为
表示层:数据格式化、代码转换、数据加密,字符串编码解码等
确保数据发送出去后可以被理解
会话层:建立,解除会话
传输层:提供端对端的接口,tcp
提供主机到主机的数据通信能力
网络层:为数据包选择路由,ip,icmp
数据链路层:传输有地址的帧
提供了数据在设备与设备间的传输能力
物理层:二进制的数据在物理媒体上传输数据,物理层是规定传输媒体接口的标准
案例:微信聊天
用户提交的输入被微信存储成某种内部格式——应用层
数据被转换成传输用的格式(如加密、压缩等)——表示层
微信客户端建立到服务器的连接——会话层
微信客户端向服务器传输数据——传输层
数据帧在一个个设备之间传输——数据链路层
数据最终以光电信号的形式再物理设备间传输——物理层
2、TCP/IP模型
TCP/UDP属于传输层协议,IP属于网络层协议
TCP/IP体系结构的优点
1、简化了计算机网络的结构,由原来的七层变成现在的四层,但是功能并没有减少
2、每一层既独立又有联系
1、网络接口层
功能:实现了网卡接口的网络驱动程序,以处理数据在物理媒介(如以太网、令牌环网等)上的传输
对应设备:网线、网桥、集线器、交换机
常用协议:
(1)ARP(地址解析协议):它实现IP地址到物理地址(MAC地址)的转换
(2)RARP(逆地址解析协议):它与ARP是相反的,它是实现从物理地址到IP地址的转换
2、网络层
功能:实现数据包的选路和转发
对应设备:路由器
常用协议:
(1)ip协议:根据数据包的目标ip地址来决定如何将它发送给目标主机。如果数据包不能直接发送给目标主机,那么ip协议为它寻找一个合适的下一跳路由器,将数据包交给路由器来转发,多次之后数据包将到达目标主机,或者因发送失败而被丢弃
(2)ICMP协议是网络层的另一个重要协议,它是ip协议的重要补充,主要用于检测网络连接
3、传输层
功能:为两台主机上的应用程序提供端到端的通信。与网络层使用的逐跳通信不同,传输层只关心通信的起始端和目的端,而不在乎数据包的中转过程
主要协议:
(1)TCP(传输控制协议):为应用层提供可靠的、面向连接的河流式服务
(2)UDP(用户数据报协议):为应用层提供不可靠的、无连接的和数据报服务
4、应用层
功能:负责处理应用程序的逻辑、比如文件传输,名称查询和网络管理等
常用协议:
(1)OSPF(开放最短路径优先)协议:是一种动态路由更新协议,用于路由器之间的通信,以告知对方各自的路由信息
(2)DNS(域名服务)协议:提供及其域名到IP地址的转换
(3)telnet协议是一种远程登录协议,使我们能在本地完成远程任务
(4)HTTP协议(超文本传输协议)是一个基于请求与响应模式的、无状态、应用层的协议,常基于TCP的连接方式
3、TCP协议
客户端与服务器之间数据的发送和返回的过程需要创建一个TCP connection的连接
TCP报文格式
1、序号(sequence number):seq序号,占32位,用来标识从TCP源端向目的端发送的字节流(发起方发送数据时的标记)
2、确认号(acknowledge number):Ack序号,占32位,只有ACK标志位为1时,确认号字段才有效,Ack = Seq + 1
3、标志位(Flags):URG、ACK、PSH、RST、SYN、FIN
| 字段 | 含义 |
|---|---|
| ACK | 确认序号有效,一般置为1 |
| PSH | 接收方应该尽快将这个报文交给应用层 |
| RST | 重置连接 |
| URG | 紧急指针有效 |
| SYN | 发起一个新连接 |
| FIN | 释放一个连接 |
注:确认号Ack与标志位中的ACK是不一致的。确认方Ack = 发起方Seq + 1
4、TCP连接3次握手
三次握手即TCP连接的建立,这个连接必须是一方主动打开,另一方被动打开
握手之前主动打开连接的客户端结束CLOSED阶段,被动打开的服务器端也结束CLOSED阶段,并进入LISTEN阶段,随后开始“三次握手”
(1)第一次握手
首先客户端向服务器端发送一段TCP报文:
- 标志位为SYN,表示请求“建立新的连接”
- 序号为Seq = x (x一般为1)
- 随后客户端进入SYN-SENT阶段
(2)第二次握手
服务器端收到来自客户端的TCP报文之后,结束LISTEN阶段。并返回一段报文:
- 标志位为SYN和ACK,表示“确认客户端的报文Seq序号有效,服务器能正常接收客户端发送的数据,并同意创建新连接“
- 序号为Seq = y
- 确认号为Ack = x + 1,表示收到了客户端的序号Seq并将其值加1作为自己确认号Ack的值。随后服务器端进入SYN-RCVD阶段
(3)第三次握手
客户端接收到来自服务器的确认收到的TCP报文之后,明确了从客户端到服务器的数据传输是正常的,结束SYN-SENT阶段,并返回最后一段TCP报文:
- 标志位为ACK,表示“确认收到服务器端统一连接的信号”
- 序号为seq = x + 1,表示收到服务器端的确认号Ack,并将其值作为自己的序号值
- 随后客户端进入ESTABLISHED阶段
在客户端与服务器端传输的TCP报文中,双方的确认号Ack和Seq的值,都是在彼此Ack和Seq值额度基础上进行计算的,这样做保证了TCP报文传输的连贯性,一旦出现某一方发出的TCP报文丢失,便无法继续“握手”,以此确保“三次握手”的顺利完成。
此后,客户端和服务器端进行正常的数据传输,这就是“三次握手”的过程
为什么要进行第三次握手?
- 确认双方的通信能力:通过三次交互,确保客户端和服务器都能正常收发数据。
- 同步初始序列号:双方交换并确认初始序列号,为后续数据传输提供基础。
- 防止失效的连接请求:如果客户端之前发送的SYN报文因网络延迟而晚到,服务器会误认为是新的请求。第三次握手让客户端有机会告知服务器该请求已失效,避免建立无效连接。
三次握手可以都可以携带数据吗?
答:第三次握手可以携带数据,但是第一次、第二次握手不可以携带数据
第一次握手不可以放数据,其中一个原因是会让服务器变得更加容易受到攻击(每次发送的SYN报文携带大量数据,无数次发送给服务器,严重影响服务器性能)
而对于第三次握手,此时客户端已经处于ESTABLISHED状态,连接已经建立起来,双方的接受、发送能力是正常的,携带数据也就很正常
ISN是固定的吗
三次握手的一个重要功能是客户端和服务端交换ISN,以便让对方知道接下来接受数据的时候如何按序列号组装数据
如果ISN是固定的, 攻击者很容易猜出后续的确认号,因此ISN是动态生成的
什么是半连接队列
服务器第一次收到客户端的SYN之后,会处于SYN-RCVD状态,此时双方还没有完全建立起连接,服务器会把这种状态下请求连接放进一个队列里,我们把这种队列称之为半连接队列
5、TCP连接4次挥手
概述:四次挥手即TCP连接的释放(解除)。连接的释放必须是一方主动释放,另一方被动释放
挥手之前主动释放连接的客户端结束ESTABLISHED阶段,随后开始“四次挥手”
1、第一次挥手
首先客户端想要释放连接,向服务器端发送一段TCP报文
- 标志位为FIN,表示“请求释放连接”
- 序号为Seq = U
- 随后客户端进入FIN-WAIT-1阶段,即半关闭阶段,并且停止在客户端到服务器端方向上发送数据,但是客户端仍然能接收从服务器端传输过来的数据
2、第二次挥手
服务器端接收到从客户端发出的TCP报文之后,确认客户端想要释放连接,随后服务器器端结束ESTABLISHED阶段,进入CLOSE-WAIT阶段(半关闭状态)并返回一段TCP报文
- 标志位为ACK,表示“接收到客户端发送的释放连接的请求”
- 序号为Seq = V
- 确认号为Ack = U + 1,表示是在收到客户端报文的基础上,将其序号Seq值加1作为本段报文确认号Ack的值
- 随后服务器端开始准备释放服务器端到客户端方向上的连接
客户端收到从服务器端发出的TCP报文之后,确认服务器收到了客户端发出的释放连接请求,随后客户端结束FIN-WAIT-1阶段,进入FIN-WAIT-2阶段
前“两次挥手”既让服务器端知道了客户端想要释放连接,也让客户端知道服务器端了解自己想要释放连接的请求。于是确认关闭客户端到服务器端方向上的连接
3、第三次挥手
服务器端自动发出ACK确认报文之后,经过CLISED-WAIT阶段,做好了释放服务器端到客户端方向上的连接准备,再次向客户端发出一段TCP报文,其中:
- 标志位为FIN,ACK,表示“已经准备好释放连接了”。注:这里ACK并不是确认收到服务器端报文的确认报文
- 序号为Seq = W
- 确认号为Ack = U + 1,表示是在收到客户端报文的基础上,将其序号Seq值加上1作为本段报文确认号Ack的值
随后服务器端结束CLOSE-WAIT阶段,进入LAST-ACK阶段,并且停止在服务器端到客户端的方向上发送数据,但是服务器端仍然能够接收从客户端传输过来的数据
4、第四次挥手
客户端收到服务器发出的TCP报文,确认服务器端已做好释放连接的准备,结束FIN-WAIT-2阶段,进入TIME-WAIT阶段,并向服务器端发送一段报文,其中:
- 标志位ACK,表示“接收到服务器准备好释放连接的信号”
- 序号Seq = U + 1,表示是在收到了服务器端报文的基础上,将其确认号Ack值作为本段报文序号的值
- 确认号Ack = W +1;表示是在收到了服务器端报文的基础上,将其序号Seq值作为本段报文确认号的值
随后客户端开始在TIME-WAIT阶段等待2MSL
服务器端收到客户端发出的TCP报文之后结束LAST-ACK阶段,进入CLOSED阶段。由此正式确认关闭服务器端到客户端方向上的连接
客户端等待2MSL之后,结束TIME-WAIT阶段,进入CLOSED阶段,由此完成“四次挥手”
后“两次挥手”既让客户端知道了服务器端准备好释放连接了,也让服务器知道了客户端了解自己准备好释放连接了。于是,可以确认关闭服务器端到客户端方向上的连接,由此完成了“四次挥手”
与“三次挥手”一样,在客户端与服务器端传输的TCP报文中,双方的确认号Ack和序号Seq的值,都是在彼此Ack和Seq值的基础上进行计算的,这样做保证了TCP报文传输的连贯性,一旦出现包一方发出的TCP报文丢失,便无法继续“挥手”,一次确保“四次挥手的顺利完成”
问题
1、为甚么“握手”是三次,“挥手”要四次
TCP建立连接时之所以只需要"三次握手",是因为在第二次"握手"过程中,服务器端发送给客户端的TCP报文是以SYN与ACK作为标志位的。SYN是请求连接标志,表示服务器端同意建立连接;ACK是确认报文,表示告诉客户端,服务器端收到了它的请求报文。
即SYN建立连接报文与ACK确认接收报文是在同一次"握手"当中传输的,所以"三次握手"不多也不少,正好让双方明确彼此信息互通。
TCP释放连接时之所以需要“四次挥手”,是因为FIN释放连接报文与ACK确认接收报文是分别由第二次和第三次"握手"传输的。为何建立连接时一起传输,释放连接时却要分开传输?
建立连接时,被动方服务器端结束CLOSED阶段进入“握手”阶段并不需要任何准备,可以直接返回SYN和ACK报文,开始建立连接。释放连接时,被动方服务器,突然收到主动方客户端释放连接的请求时并不能立即释放连接,因为还有必要的数据需要处理,所以服务器先返回ACK确认收到报文,经过CLOSE-WAIT阶段准备好释放连接之后,才能返回FIN释放连接报文。
- TCP连接是双向的,双方需要分别确认关闭。
- 第二次挥手是确认收到关闭请求,第三次挥手是请求关闭另一方向,第四次挥手是最终确认。
- 四次挥手确保了双方都能安全关闭连接,避免数据丢失。
2、为什么客户端在TIME-WAIT阶段要等2MSL?
为的是确认服务器端是否收到客户端发出的ACK确认报文
当客户端发出最后的ACK确认报文时,并不能确定服务器端能够收到该段报文。所以客户端在发送完ACK确认报文之后,会设置一个时长为2MSL的计时器。MSL指的是Maximum Segment Lifetime:一段TCP报文在传输过程中的最大生命周期。2MSL即是服务器端发出为FIN报文和客户端发出的ACK确认报文所能保持有效的最大时长。
服务器端在1MSL内没有收到客户端发出的ACK确认报文,就会再次向客户端发出FIN报文;
如果客户端在2MSL内,再次收到了来自服务器端的FIN报文,说明服务器端由于各种原因没有接收到客户端发出的ACK确认报文。客户端再次向服务器端发出ACK确认报文,计时器重置,重新开始2MSL的计时;否则客户端在2MSL内没有再次收到来自服务器端的FIN报文,说明服务器端正常接收了ACK确认报文,客户端可以进入CLOSED阶段,完成“四次挥手”。
- 主动关闭方在发送最后一次ACK后,会进入
TIME_WAIT状态,等待2MSL(Maximum Segment Lifetime)。 - 作用:
- 确保被动关闭方收到ACK,如果未收到,被动关闭方会重发FIN。
- 让网络中残留的报文段消失,避免影响新连接。
6、TCP与UDP的区别
UDP——User Data Diagram
比TCP节省网络资源,更加迅速
不需要建立连接(延迟更低),封包体积更小(传输速度快),不关心数据顺序(不需要序号和ACK,传输快速),不保证数据不丢失
TCP建立连接需要三次握手,但是UDP直接传输即可,不保证数据可达
UDP通信不保证顺序
思考:UDP没有虚拟链接,不校验数据、不保证顺序、没有收到不重发是不是意味着不安全、不可靠
答:并不是,UDP自由度更高,这意味着需要用户程序在应用层定义类似的机制。
