大文件传输,前后端分别如何处理
- 为什么要做额外处理
- 文件过大会超出服务端请求限制。例如SpringMVC,默认文件上传最大1MB
- 请求时间过长,请求超时
- 客户端网络不好,会容易传输中断,必须整个文件重新传输
- 如何处理
- 前端处理:将大文件进行分片处理,利用Blob.prototype.slice()方法对文件切片。分发多个请求,后端根据分片的下标和Size向磁盘的不同位置写入分片数据。
- 后端处理:后端接收到分片数据后,要根据分片的下标和分片的大小来往文件的指定位置写入分片数据。待所有的分片数据全部写完,就能得到一个完整的文件。
//生成文件切片 //上传切片 - 断点续传 在切片上传的过程中,如果已经传了一些切片然后因为系统崩溃或者网络中断等一场因素导致上传中断,这时就需要记录上传的进度。
下一次传输时,服务器返回接口显示成功传送切片的信息,就可以从当前位置继续传输。或者服务器返回信息已经传送过该切片,则不再传输已经传输过的切片。
- 实现的两种方式
- 前端使用local Storage记录已经上传的切片hash
- 服务器保存已经上传的切片hash,前端每次上传前向服务器获取已经上传的切片。
- 秒传 上传文件时,服务器先做MD5校验,如果服务器中有一样的文件,就不再重复上传,直接返回该文件存放在服务器的url。没有上传过则进行上传。
XSS攻击与CSRF攻击
XSS攻击
- XSS攻击是什么
- 跨站点脚本攻击,通过注入脚本,并运行在用户的浏览器中,获取用户的信息,cookie或者sessionID等
- 具体有哪些XSS攻击方式?特点
- 在页面中用户输入的信息未做转义,攻击者会利用用户输入的代码片段,拼接上特殊格式字符串比如script标签,或者一些引号,突破一些标签、属性的限制,形成代码片段被注入到网页中。然后这些内容经浏览器渲染,在用户的浏览器中运行。
- 虽然做了转义,但比如一些a标签或者img标签里面的href、src属性,可能会包含javascript:这样的可执行代码,这样用户点击时就会执行这些代码。
- onload、onerror、onclick中的事件中注入不受控制的代码。
- 类型
- 存储型。用户输入包含恶意代码的信息,通过表单提交等输入信息被存储到数据库中。浏览器在从数据库中获取数据渲染到页面的时候,恶意代码就会被执行。
- 反射型,诱导用户打开一段url,里面拼接了一些代码片段。
- 如何防范
- HTML转义,对用户输入的内容做转义,这样即使是script标签等特殊内容,也会被渲染成文本。
- 对于a标签内的href src属性,设置白名单(Content Security Policy),禁止掉javascript链接和其他非法形式(外域代码,内联脚本,外域提交),只允许http,https等,其他都跳转到404.cookie中设置httpOnly。
- 尽量避免使用innerHTML,document.write,等方法,使用安全性更高的textContent,setAttribute等方式替代。
- 避免使用内联事件,主动做检测等等。
CSRF攻击
- CSRF攻击
- 跨站点请求伪造。诱导用户进入第三方网站,然后进入以后向被攻击的网站发送跨域请求,因为这时用户还保留着登陆状态,因此可以利用已经登录的状态冒充用户执行一系列操作。
- 具体有哪些
- GET类型:当前页面中图片里面隐藏一个链接,诱导用户跳转页面,然后以用户的身份进行操作
- Post类型:通过一个诱导用户点击的超链接,用户点进去以后网页中包含一个自动提交的表单,模拟用户完成一系列的POST操作。
- 有哪些特点?
- 通常是发生在第三方网站,而不是被攻击的网站
- 是利用用户的登录状态,冒充用户进行操作,而不能获取到用户的登录凭证
- 请求方式主要通过图片、超链接、 表单等
- 发送的请求一般是跨域的。
- 如何防范?
- 响应头中设置Cookie的sameSite属性:Strict(跨站点不会发送cookie),Lax(大多数情况不发送第三方Cookie)
- 同源检测:因为一般是发生在第三方网站中,发送的请求一般是跨域的。因此可以对请求进行同源检测,阻止不明外域的访问,监测外域的请求。具体做法是Http请求头中验证HTTP Refer、Origin字段,判断请求来源。
- 通过Token验证。因为CSRF攻击一般是把攻击者发送的请求去当作是用户发送的请求,因此可以让用户发送请求的时候携带一个攻击者获取不到的Token信息,然后让服务端进行校验。服务端生成token,前端保存在local-Storage或者Session-Storage中,之后每次请求都要带上,第三方网站无法获取到token,因此服务器可以识别是否为第三方网站的请求。
- 通过双重Cookie验证、二次验证。因为CSRF攻击并不能获取到用户的Cookie信息,只是利用已有的cookie信息进行操作,因此可以多进行一次cookie验证。或者通过手机验证码、邮箱验证等方式进行二次验证。
XS-Leaks
- 跨站泄露:利用了对http缓存进行查询到机制,通过对资源缓存的判断进而推断出当前用户的相关信息。
渐进增强与优雅降级
- 渐进增强
- 针对低版本浏览器构建页面,保证基本的功能,然后针对高版本浏览器进行优化,追加功能,改进交互等用户体验
- 优雅降级
- 一开始就构建完整的功能,然后再针对低版本的浏览器做兼容性。
cdn原理
- cdn Content Delivery Network,内容分发网络。这个网络中有许多边缘服务器提供服务,帮服务器给用户就近分发网络内容。
- 总的来说就是为了提升用户访问页面的速度,但是如果只是考虑浏览器缓存,进能够提高二次访问的速度,对于首次访问的速度,需要从网络层进行优化,最常见的手段就是CDN加速,将静态资源缓存到距离用户很近的CDN节点上。
- 原理
- 是构建在现有网络基础上的智能虚拟网络,CDN服务商在全国各个省份部署计算节点,在用户访问网站时,通过中心平台上的负载均衡技术,内容分发,调度等功能模块,(在CDN网络中寻找一台各种条件比较适合,距离最近的服务器,)将用户的访问指向距离最近的缓存服务器中,由缓存服务器直接响应,使用户可以就近获取所需内容。
- 降低网络拥堵,提高用户访问响应速度和命中率。
CDN负载均衡算法
- 静态负载均衡
- 轮询法:将请求轮流分配到每个节点上。没有考虑机器的性能问题,集群性能更多的会受到性能差的服务器影响
- 随机法:将请求随机分配到各个节点。随着客户端调用服务器次数增多,实际效果越来越接近于平均分配
- 源地址哈希法:根据客户端的IP地址,通过哈希函数得到一个数值,用该数值对服务器节点进行取模,得到的结果就是访问节点序号。优点:相同的IP地址会每次落在同一个节点,可以人为干预客户端请求方向。缺点:如果某个节点出现故障,就会导致该节点的客户端无法使用。
- 加权轮询法:给配置高,负载低的机器配置更高的权重
- 加权随机法
- 键值范围法
- 动态负载均衡
- 最小连续数法:根据每个节点当前的连接情况,动态的选取当前积压连接数最少的一个节点处理当前请求
- 最快响应速度法:根据请求的响应时间,动态调整每个节点的权重,将响应速度快的服务节点分配更快的请求。
- 观察模式法:结合了最小连接数和最快相应度法,同时考量两个指标数,进行一个权重的分配。
浏览器输入URL以后发生了什么?
- 解析URL 当在浏览器中输入URL,浏览器首先对拿到的URL进行识别,取出域名字段
- DNS解析通过递归查询或者迭代查询,找到与域名对应的IP地址,然后向该IP地址定位到的服务器建立TCP连接。
- 浏览器搜索自己浏览器的DNS缓存,如果没有就搜索本地操作系统中的DNS缓存和hosts文件。
- 如果没有,操作系统将域名发送给本地域名服务器,本地域名服务器查询自己的DNS缓存,查找成功返回结果,否则依次向根域名服务器,顶级域名服务器、权限域名服务器发起查询请求。
- 通过以上查找,就可以获取到域名对应的IP了
- 接下来就可以向该IP地址定位的Http服务器发起TCP连接
- 浏览器与网站建立TCP连接(三次握手)
- TCP协议是传输层面向连接的一个安全可靠的协议。三次握手的机制是为了确保能进行安全可靠的连接。 - 第一次握手由客户端向服务器发起,客户端会向服务器发送一个报文,报文中SYN=1
- 当服务端收到这个报文,就知道客户端想要连接,会向客户端返回确认报文,这个报文中SYN=1,ACK=1,并且携带一个确认序列号。
- 以上两次握手之后,客户端可以确认自己能够向服务器发送报文并且自己发送的报文能够被服务端接收到。但是对服务端两次握手是不够的,服务端只知道自己能够接收到客户端发送的报文,但是自己发送的报文不知道是否会被客户端接收到。因此需要第三次握手
- 第三次握手由客户端向服务器发起,向服务端发送一个确认收到的报文,ACK=1,且携带确认序号。
- 经过三次握手之后,客户端和服务端都能够直到自己既能够向对方发送消息,也能够确认对方可以收到消息。
- 请求与传输数据
- 客户端发送http请求,如果协议是Https则会做加密
- 检查是否会命中强制缓存和协商缓存。
- 从本地获取资源或者服务器响应请求,返回资源,返回给浏览器html文件
- 浏览器渲染页面
- 解析html源码,创建一个DOM树。
- 解析CSS代码,计算出最终的样式数据,形成CSSOM
- 结合DOM树和CSS规则树,最终形成渲染树
- 根据渲染树计算每个节点的信息,根据计算好的信息绘制页面。
- 页面加载完毕(window.onload)
- 断开TCP连接(四次挥手)
- 四次挥手也是由客户端首先发起,客户端会发送一个报文,报文中FIN位置1
- 当服务端收到客户端想要断开连接的报文,服务端可能还会有未发送的数据。所以要先向客户端发送报文说明自己确认收到了释放连接的请求,但是还需要进行一些断开连接前的准备。因此报文中ACK=1,且发送一个确认序号代表收到了客户端想要断开连接的请求。
- 过一段时间以后,等服务端做好准备,发送完所有数据,准备好断开连接,会继续向客户端发送连接释放报文段,FIN=1,ACK=1且携带一个确认序号
- 客户端收到以后会回复一个确认报文段,并且等待一段时间之后连接彻底关闭。报文中ACK=1.且携带一个确认序号
- 通过四次挥手的过程后不管是客户端还是服务端都已经做好了断开连接的准备,这时就可以释放连接
浏览器渲染页面的过程
浏览器渲染页面的过程即从服务器获取Html或者本地获取Html资源以后,对html文件进行解析,渲染页面的过程。
- 将获取的HTML文档解析构建DOM树
- DOM树构建过程可能会被CSS和JS加载导致执行组森
- display:none,script标签,注释都会出现在DOM中
- 浏览器解析CSS文件生成CSSOM
- CSS解析可以与DOM解析同时执行,但是不能与script同时执行
- 访问js时停止css
- 将DOM树与CSSOM合并成为渲染树
- DOM树与渲染树区别:不出现在页面中的元素不会在渲染树中,display:none,但是visibility:hidden有占位,可以出现在渲染树中。
- 布局阶段,从渲染树的根节点遍历,通过样式信息确定每个节点在页面中的确切大小和位置。
- 将渲染树各个节点绘制到屏幕上(painting)
渲染阻塞
- 解析script标签导致的渲染阻塞
- 由于js可以操作DOM改变DOM结构,也就而已操作CSSOM改变节点样式。因此浏览器解析html文件遇到script标签时会停止构建DOM,直到脚本运行完成再继续构建。外部脚本也会等待脚本下载完毕再解析文档。
- js阻塞了构建DOM和CSSOM,所以必须等待js执行完才能够继续,称为js的阻塞页面。
- 解析CSS文件导致的渲染阻塞
- 只有CSSOM和DOM全部解析完毕(可以同时构建DOM和CSSOM),才会进行下一步渲染。称为CSS阻塞渲染
- 因此在CSSOM构建完成之前页面将一直处于白屏状态,所以样式放在head中可以尽快解析CSS,保证更快的首屏渲染。
script标签的defer和async
- 为什么设置defer与async?
- 因为浏览器在解析html渲染页面,遇到script标签会立刻执行,外部的js文件会立刻下载并执行,无法继续构建dom,必须等待脚本的下载。
- 为了防止script标签js文件下载导致的渲染阻塞,影响用户体验,可以通过合理使用defer属性和async属性,调整脚本的下载和执行顺序,使其不阻塞页面加载
- defer:开启新的线程下载脚本文件,脚本在文档解析完成以后执行
- 只适用于外联脚本,如果没有src,不用defer
- 多个defer按顺序下载和执行
- defer脚本会等待文档中元素解析之后执行。
- async:异步下载脚本文件,下载完立即执行代码
- 只适用于外联脚本
- 多个async不能保证先后顺序,哪个先下载好就立即执行哪个
- 在load之前执行
- 相比不设置defer和async的普通script标签,单线程,文档解析时会暂停开始下载并解析js文件。
重排(回流)与重绘
重排(回流)(reflow)
- 什么是重排(回流)(reflow)
- 某个子元素的样式发生改变,会影响到它所关联到的的所有元素(父元素、祖先元素。。。),这个时候浏览器需要重新渲染这个子元素相关联的所有元素。布局发生了变化,需要倒回去重新渲染。
- 回流的过程,从root开始递归,以此计算所有节点的位置和尺寸,确认是渲染树的部分发生改变还是整个渲染树的改变。
- 什么情况会导致重排
- 页面的首次渲染
- DOM树的变化:元素内容,元素大小数量,添加或者删除dom元素
- 操作class属性,设置style,激活伪类比如:hover,改变了页面默认的字体,改变了padding。。。(css:元素位置,尺寸,padding,margin,字体大小,类型,。。)
- 查询属性:offsetLeft,offsetTop,offsetHeight,scrollTop/Left/Width/height,client//
- 改变浏览器的窗口大小
重绘(repaint)
- 什么是重绘
- 页面中元素样式改变不影响位置。比如只改变了颜色、文字颜色,不影响周围和内部的布局。回流必然引发重绘。
如何减少重绘和重排?
- 为什么要减少?
- 重绘和重排会大大影响web性能
- 不停改变页面的布局,浏览器对页面的计算开销巨大,用户使用时容易发生卡顿。
- 如何减少?
- 减少使用获取页面中的属性比如offsetxxx,scrollxxx,clientxxx
- 减少DOM操作,获取元素,添加style,修改DOM等。
- 修改节点样式尽量一次性修改
- 先将节点设置display:none,再对节点进行多次操作
页面加载时触发的事件及顺序
- 开始解析HTML文档结构
- 加载外部样式表js脚本
- 执行js脚本
- DOM树渲染,渲染完成触发DOMContentLoaded事件
- 加载未完成的外部资源,window.onload
- 加载成功
OSI七层模型
-
应用层:
- 包括所有与用户交互产生网络流量的程序。
- 定义了应用进程之间的交互规则,通过不同的应用层协议为不同的网络应用提供服务。典型的应用层服务有:HTTP协议,文件传输FTP协议,电子邮件系统采用的SMTP协议。在应用层交互的数据单元称为报文。
-
表示层:
- 用于处理两个设备之间的数据传递。
- 功能:数据格式变换,代码转换,使应用程序不必担心在各台计算机中表示存储的内部格式差异。
- 功能2:数据加密解密。比如密码的加密解密
- 功能3:数据压缩和恢复:例如视频聊天,传输的图像非常大,需要先压缩,传输然后解压缩
-
会话层:
- 向表示层或者用户进程提供建立连接,并在连接上有序的传输数据。建立会话与解除会话。
- 功能1:建立、管理、终止会话
- 功能2:使用校验点,可使会话在通信失效时从校验点/同步点继续回复通信,实现数据同步。比如传输大文件(断点续传)
-
传输层:
- 为主机两个进程之间的通信提供服务。提供端对端的通信
- 功能:可靠传输(有确认机制),不可靠传输(小的数据包不需要确认机制)。差错控制(如果数据包错乱可以在传输层得到纠正)。流量控制(发送许许多多的数据,接收方可以控制发送方的发送速度)。复用分用(复用:多个应用层进程可以同时使用下面运输层的服务,分用:运输层把收到的信息分别交付给应用层相应的进程)。
- 主要的传输层协议是tcp/udp
-
网络层:
- ip层/网际层。
- 把分组从源端传到目的端,为分组交换网上的不同主机提供通信服务。为数据包选择路由。
- 传输单位:数据报。
- 功能:路由选择(选择最佳路径,)。流量控制(协调发送端与接收端的传输速度问题)。差错控制(通信两节点校验规则,纠错)。拥塞控制(如果所有节点都来不及分组,网络处于拥塞状态,这时需要采用一定措施缓解拥堵,全局控制速度)。
- 使用的协议是无连接的网际协议和许多路由协议。IP、IPX、ICMP、IGMP、ARP、RARP、OSPF
-
数据链路层:
- 把网络层传下来的数据报组装城帧
- 传输单位:帧。每一帧的数据可以分成报头和数据两部分。
- 功能:定义帧的开始和结束。差错控制(帧错和位错)。流量控制(发送方接收方的速度协调)。控制对信道的访问。
- 协议:SDLC、HDLC、PPP、STP
-
物理层:
- 二进制的数据形式在物理媒体上进行比特流的透明传输。透明传输(不管数据是什么样的比特组合都可以在链路上传输)
- 传输单位:比特
- 功能:定义接口特性(确定电缆接口插头)。定义传输模式(单工,半双工,双工)。定义传输速率。比特同步。比特编码。
- 协议:Rj45,802.3
TCP/IP参考模型,五层模型
TCP/IP四层模型
- 应用层(应用、表示、会话)
- 各种网络应用。与用户交互产生网络流量的进程。包括设备中的各种应用软件。
- 不同的应用程序使用不同的应用层协议。HTTP协议,FTP文件传输协议,电子邮箱系统协议SMTP,将域名转换为ip的DNS协议
- 传输层
- 主机中进程与进程之间的数据传输,端到端的通信
- TCP、UDP
- 网际层
- 负责将数据从一个设备传输到另一个设备
- 网络接口层(链路、物理)
五层模型
- 应用层(应用、表示、会话)
- 支持各种网络应用
- HTTP、FTP、SMTP
- 传输层
- 进程与进程之间的数据传输
- TCP、UDP
- 网际层(网络层)
- 源主机到目的主机的数据分组路由与转发。负责为分组网络中的不同主机提供通信服务,并通过选择合适的路由将数据传递到目标主机。
- IP、ICMP、OSPF
- 数据链路层
- 把网络层传下来的数据报组装成帧
- Ethernet、PPP
- 物理层
- 比特传输
- Rj45,802.3
TCP与UDP协议
TCP
- 面向连接的传输控制协议
- 面向连接:传送数据之前必须建立连接,数据传送结束之后要释放连接。
- 由于面向连接:不可避免地增加了许多开销,确认、流量控制、计时器、连接管理
- 每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的一对一的。因此不提供广播或者多播服务
- TCP提供可靠交付的服务,可靠有序,不丢不重,TCP是有状态的,会精准记录哪些数据发送了,哪些数据被接受了,保证数据包按序到达。TCP遇到丢包问题或者网络环境不佳,TCP会根据具体情况调整行为,控制自己的发送速度或者重发。
- TCP提供全双工通信,双方可以同时是发送方也可以同时接收。因此TCP双方都会设置发送缓存和接收缓存
- TCP是面向字节流的。TCP把应用程序中的数据看成一连串无结构的字节流。
- 特点:可靠的协议,面向连接,有时延,适用于大文件
- TCP报文段的首部格式
UDP
- 无连接的用户数据报协议。
- 无连接:传送数据之前不需要建立连接,收到UDP报文之后也不需要给出任何确认。减少开销和发送数据之前的时延。
- 不保证可靠交付
- 面向报文,适合一次性传输少量数据的网络应用。接收到应用层的报文不做拆分也不做改动,整个报文都会放到UDP的数据报中
- 无拥塞控制,适合很多实时应用。
- UDP首部开销小8B
- 特点:不可靠的连接,无连接的协议,时延小,适用于小文件
- UDP首部格式
- 包括8个字节的首部字段和剩下的数据字段。
TCP连接建立与连接释放(三次握手与四次挥手)
三次握手:
- 运行在一台主机上的一个进程想与另一台主机上的一个进程建立连接。
- 客户端发送连接请求报文段,不包含应用层数据。六个控制位中:同步位SYN=1(代表连接请求),序列号seq=x(随机)
- 服务器端为该TCP连接分配缓存和变量,并向客户端返回确认报文段,允许连接,无应用层数据。同步位SYN=1(代表连接请求接受),确认位ACK=1,seq=y(随机),确认号字段ack = x+1。
- 客户端为该TCP连接分配缓存和变量,并向服务器返回确认的确认,可以携带数据。同步位SYN=0,ACK=1,seq=x+1,ack=y+1
- 总结:
- TCP协议是传输层面向连接的一个安全可靠的协议。三次握手的机制是为了确保能进行安全可靠的连接。 - 第一次握手由客户端向服务器发起,客户端会向服务器发送一个报文,报文中SYN=1
- 当服务端收到这个报文,就知道客户端想要连接,会向客户端返回确认报文,这个报文中SYN=1,ACK=1,并且携带一个确认序列号。
- 以上两次握手之后,客户端可以确认自己能够向服务器发送报文并且自己发送的报文能够被服务端接收到。但是对服务端两次握手是不够的,服务端只知道自己能够接收到客户端发送的报文,但是自己发送的报文不知道是否会被客户端接收到。因此需要第三次握手
- 第三次握手由客户端向服务器发起,向服务端发送一个确认收到的报文,ACK=1,且携带确认序号。
- 经过三次握手之后,客户端和服务端都能够直到自己既能够向对方发送消息,也能够确认对方可以收到消息。
四次挥手:
- 参与一条TCP连接的两个进程中任何一个都能终止连接,连接结束后,主机中的缓存和变量将被释放。
- 客户端发送连接释放报文段,停止发送数据,关闭TCP连接。结束位FIN=1,seq = u。
- 服务器端返回一个确认报文段,客户到服务器方向的连接就释放了。客户端不再发送数据但是服务端还可以再发送。ACK=1,seq=v,ack=u+1
- 服务器发送完数据,发出连接释放报文段,主动关闭TCP连接。FIN=1,ACK=1,seq=w,ack=u+1
- 客户端回复一个确认报文段,等到时间等待计时器设置的2MSL(最长报文段寿命)后,连接彻底关闭。ACK=1,seq=w,ack=w+1
- 总结
- 四次挥手也是由客户端首先发起,客户端会发送一个报文,报文中FIN位置1
- 当服务端收到客户端想要断开连接的报文,服务端可能还会有未发送的数据。所以要先向客户端发送报文说明自己确认收到了释放连接的请求,但是还需要进行一些断开连接前的准备。因此报文中ACK=1,且发送一个确认序号代表收到了客户端想要断开连接的请求。
- 过一段时间以后,等服务端做好准备,发送完所有数据,准备好断开连接,会继续向客户端发送连接释放报文段,FIN=1,ACK=1且携带一个确认序号
- 客户端收到以后会回复一个确认报文段,并且等待一段时间之后连接彻底关闭。报文中ACK=1.且携带一个确认序号
- 通过四次挥手的过程后不管是客户端还是服务端都已经做好了断开连接的准备,这时就可以释放连接
为什么是三次握手不是两次?四次?
-
两次:
- 两次握手之后客户端可以确认既可以想服务端发送请求,也可以确认发送的请求服务端可以接收到。但是对于服务端两次握手是不够的,服务端这时只知道自己可以接收客户端发送的请求,但是不知道自己发送的请求能否被客户端接收。
- 并且为了防止已经失效的连接请求报文突然又传输到了服务端,导致产生问题。比如客户端发送连接请求,由于网络阻塞等原因服务器没有收到,因此客户端没有收到确认保温就会重发连接请求。连接成功后传输完成释放连接。然后客户端发送的第一个请求在某个时间到达服务器以后,服务器误认为是新的连接请求,又会建立新的连接,但是此时服务器不会受到任何数据,浪费了资源。
-
四次:足够确认两方可以发送可以接受
为什么是四次挥手不是三次?
- 因为客户端发送释放连接请求以后,服务器还可能会有数据没有传输完成,需要准备一段时间再关闭连接,因此需要先告知客户端,确认收到了释放连接的报文段。
四次挥手中为什么等待2MSL?
- 为了保证客户端发送的最后一个确认ACK报文段能够到达服务器。
- 因为最后一个确认ACK有可能丢失,服务端如果收不到确认报文,就会超时重传连接释放报文段。然后客户端可以在2MSL这段时间内重发确认报文,然后重新启动2MSL计时器。就可以确保客户端和服务器都能够进入CLOSED状态。
- 如果客户端不等待2MSL,而是发送完直接关闭连接,就无法收到服务器重传的释放连接报文段,也不会重发连接,此时服务器就无法进入CLOSED状态
- 为了防止已经失效的连接请求报文段出现在本连接中。
- 客户端发送一个确认关闭报文段后,经过2MSL就可以将这个连接产生的所有报文段都从网络中消失,这样下一个新的连接中就不会出现旧的连接请求报文段。
TCP可靠传输,流量控制,拥塞控制
TCP实现可靠传输
- 数据包校验:通过在发送方和接收方增加伪首部实现。目的是检测数据在传输过程中的变化,如果校验出有错误,就不给响应。
- 对失序数据包重新排序
- 丢弃重复数据
- 重传机制:
- 超时重传。TCP的发送方法在规定时间内没有收到确认就要重传。
- 快速重传:冗余ACK确认,指明下一个期待字节的序号,如果收到三个冗余ACK就说明报文丢失进行重传。
- 流量控制:TCP连接的每一方都有固定大小的缓存空间。TCP接收端只允许另一端发送接收端的缓冲区能接纳的数据。协调发送方与接收方传输数据的速度。
流量控制
- 为什么流量控制?
- 流量控制是为了控制发送方的发送速率。如果发送方发送数据过快,接收方来不及接收就会产生丢包现象。因此需要协调发送方与接收方传输数据的速度。
- 怎么实现?滑动窗口
- TCP会话的双方都各自维护一个发送窗口和接收窗口,
拥塞控制
DNS查询
- 域名
WebSocket
- 是什么
- WebSocket是一种网络传输协议,位于OSI模型的应用层。可以在单个TCP连接上进行全双工通信,能更好的节省服务器资源带宽并且可以达到实时通信。
- 客户端和服务器只需要完成一次握手,两者之间就可以达到持久性的连接,并且进行双向数据传输。
- 过程
- WebSocket服务器与客户端通过握手连接,建立tcp连接
- 客户端发送http请求,请求中携带Connection字段为Upgrade;Upgrade字段为websocket,向服务器表明需要升级websocket协议,并且携带Sec-Websocket-key进行验证是否收到一个有效的websocket请求。
- 服务器成功建立websocket连接以后,会返回同样的Connection字段和Upgrade字段,并且返回一个Sec-Websocket-Accept,为加密过的key,表示成功建立webSocket请求。
- 成功建立连接以后,两者都能主动的向对方发送或者接受数据。
- WebSocket出现之前开发实时应用的方式
- 通过轮询的方式,不停地向服务器发送HTTP请求,问服务器有没有数据
- 有数据,服务器发送响应报文。
- 如果轮询的频率比较高就可以近似地实现实时通信的效果
- 缺点:反复发送无效查询请求,占用了大量的带宽和CPU资源。
- Websocket特点
- 全双工:通信允许数据在两个方向上同时传输。握手成功以后服务器客户端可以进行双向的数据传输,都可以主动的发送数据。
- 二进制帧:采用了二进制帧结构。语法语义和HTTP完全不兼容,帧结构与http有很大区别,相比于Http,webSocket更侧重于实时通信。
- 协议名:引入ws和wss分别代表明文和密文的webSocket协议。默认端口为80或者443,几乎与http一致
- 只需要进行一次握手。
- 与http的区别
- 数据包头部协议较小,不同于http每次请求都需要携带完整的头部。
- 更强的实时性(双工通信)。http请求需要等待客户端发起请求服务端才能响应。
- 保持创建连接状态:创建通信后,可以省略状态信息。http每次请求都需要携带身份验证。
- 更好的二进制支持。定义了二进制帧,更好的处理二进制内容
- 支持扩展:用户可以扩展webSocket协议,实现部分自定义的子协议
- 更好的压缩效果。
- 应用场景
- 弹幕
- 媒体聊天
- 协同编辑
- 基于实时位置的应用
- 实况更新
- 股票基金报价的实时更新
HTTP请求的方式
- HTTP1.0 GET POST HEAD
- HTTP1.1 新增了OPTIONS PUT PATCH DELETE TRACE CONNECT
- 最常用,GET POST PUT DELETE
GET和POST请求
- 联系
- 本质上建立的都是TCP连接
- 区别
- 传递数据的方式:GET参数通过URL传递,POST放在请求体中。
- 参数长度的限制(容量):GET在URL中传递的参数有长度限制,POST没有长度限制。
- 编码格式:GET请求只能进行URL编码,POST支持多种编码方式。
- 缓存:GET请求会被浏览器主动缓存,保留在浏览器的历史记录中,POST参数不会被保留,除非手动设置。
- 数据包:GET请求产生一个TCP数据包,浏览器会把请求头和data一并发送,服务器响应200返回数据。POST请求产生两个TCP数据包。先发送Header,服务器响应100 continue后,浏览器再发送data,服务器响应200返回数据。
- 安全性:GET请求不安全,参数直接暴露在URL中,不能用来存储用户的敏感信息。
HTTP常见的状态码
- 状态码 负责表示客户端HTTP请求的返回结果,标记服务器的处理是否正常,通知错误。
- 五类状态码
- 1xx 信息状态码,正在处理接受的请求
- 2xx 成功状态码,请求正常,处理完毕
- 3xx 重定向状态码,需要附加操作完成请求
- 4xx 客户端错误状态码,服务器无法处理请求
- 5xx 服务器错误状态码,服务器处理请求出错
- 几个常见的状态码
- 100 Continue 客户端继续请求
- 101 切换协议,切换到最新版本的协议
- 200OK正常处理
- 201 Created ,成功请求并创建了新的资源
- 202 Accepted ,已经接受请求但是没有处理完成
- 203 非授权信息
- 204 No Content,成功处理,但是响应报文中不含实体
- 206Partial Content,范围请求
- 301 Moved Permanently 永久移动。请求的资源已经被永久移动到新的URL,返回信息包含新的URL,浏览器重新定向到新的URL,今后都用新的URL代替
- 302 Found 临时移动。下次请求继续到原有的URL
- 303 See Other。查看其它地址
- 304 Not Modified。 未修改,所请求的资源未被修改,服务器返回状态码不会返回任何资源,客户端会缓存访问过的资源(协商缓存)
- 400 Bad Request 请求报文中含有语法错误
- 401 Unauthorized 需要认证信息,认证失败
- 403 Forbidden 没有权限,被服务器拒绝
- 404 Not Found 无法找到
- 500 服务器执行请求发生错误
- 503 服务器超负载,正在停机维修
HTTP常见的字段有哪些
- Host字段:客户端发送请求时,用来指定服务器的域名
- Content-length字段:服务器返回数据时,表明本次回应的数据长度。
- Connection:客户端要求服务器使用TCP持久连接keep-alive
- Content-Type:服务器回应时告诉客户端本次数据的格式。客户端请求时可以使用Accept字段声明自己接收哪些数据格式。
- Content-Ending:说明数据的压缩方式,表示服务器返回的数据使用的压缩格式。客户端请求时使用Accept-Ending说明自己接收哪些压缩方法。
请求和响应格式以及包含哪些信息?
请求:
- 请求行:请求类型(GET/POST/PUT/DELETE...) url路径 HTTP版本
- 请求头:
- 域名 指定请求服务器的域名和端口号
- Accept:指定能够接收的内容类型
- Cookie :
- Content-type :请求内容的类型
- 缓存相关:cache-control、If-Modified-Since、If-None-Match
- 空行
- 请求体
响应:
- 响应行:HTTP版本 状态码 短语(OK。。。)
- 响应头:
- 缓存相关:期)、Last-Modified、E-Tag
- 响应体的描述:content-type、content-language、content-length
- set-Cookie
- 空行
- 响应体
web缓存种类
- 数据库缓存
- cdn缓存
- 代理服务器缓存
- 浏览器缓存
浏览器缓存:强制缓存与协商缓存
- 浏览器缓存
- 浏览器存储了用户最近请求过的资源,当访问者再次访问,如果资源没有过期也没有被修改,就可以直接从本地加载资源。
- 缓解服务器端压力,提升性能,提高用户体验。
强制缓存
- 强制缓存
- 用户请求访问过的资源,浏览器拦截请求,查看header中的max-age字段判断资源是否过期
- 如果未过期就不会向服务器重新请求,而是从本地缓存中获取资源,会返回200状态码
- 如果过期,就会从服务器重新加载资源(未设置协商缓存),或者进入协商缓存的流程(同时设置了强缓存与协商缓存)
- 如何设置强制缓存
当访问url,向服务器发送请求,浏览器拦截请求,根据response Header判断是否设置了强缓存,查看响应头中是否有expires、pragma、cache-control字段。有的话会把资源缓存在memory cache或者disk cache中。
下一次请求时,浏览器会拦截请求,查看header中的参数(过期时间、cache-control的max-age)是否符合强缓存的条件,如果符合,返回状态码200,并且从本地缓存中读取数据。否则查看是否符合协商缓存的要求,符合(返回304),不符合服务器返回全新资源。
- Expires:绝对时间。设置未来时间,当浏览器再次加载资源,查看是否过期。
- Cache-Control:相对时间。设置max-age,在成功请求以后,如果在max-age时间之内再次请求,就走缓存。
协商缓存
- 协商缓存
- 如果强制缓存过期,或者不使用强缓存,用户请求访问过的资源时,请求头携带缓存标识,服务器根据header中的信息判断资源是否被修改。
- 检查header中是否有协商请求的标识Last-Modified和E-tag,如果没有就向服务器获取资源。
- 如果header中携带,就需要判断是否与服务器中的资源一致。如果不可用返回200和最新资源,还有最新资源标识。如果可用,返回304,服务器不返回资源,使用协商缓存获取本地资源。
- 协商缓存标识
- Last-Modified:资源上一次修改时间(服务器返回的)。if-Modified-Since(客户端携带上次的Last-Modified值),服务器会根据请求中if-Modified-Since字段和Last-Modified对比,判断资源是否更新。(200返回新资源,304代表资源未更新,继续使用缓存文件)
- E-tag:资源对应的唯一字符串(资源在服务器的缓存标识)。if-None-Match:客户端发请求时携带的上次返回的唯一标识E-tag。服务器根据请求中携带的if-None-Match和E-tag对比,(200返回新的资源文件,304资源未更新,继续使用缓存文件)
强制缓存与协商缓存的区别
- 如果资源未过期,可以从强制缓存中获取,就不会向服务器发送请求。
- 协商缓存是浏览器和服务器,经过校对标识,确定是否需要返回新的资源。
- 不常更新的静态资源设置强缓存和协商缓存。更新频繁的资源设置协商缓存。
刷新
- ctrl+f5强制刷新,直接从服务器加载,跳过强缓存与协商缓存
- f5刷新,跳过强缓存,检查协商缓存
- 浏览器地址中输入url,会走强缓存和协商缓存。
什么时候返回304?
- 当命中协商缓存的时候会返回304状态码表示资源未更新,然后从缓存中获取资源。
- 请求头if-Modified-Since(资源上一次请求时返回的last-M)和响应头中last-Modified一致。
- 请求头中if-None-Match和响应头中的E-tag一致
HTTP与HTTPS
- HTTP
- 超文本传输协议。用于在客户端和服务器之间传递信息,以明文的方式发送内容,没有任何的加密。
- 特点:支持客户端/服务器模式,简单快速,灵活,无连接,无状态
- HTTPS
- 因为HTTP是以铭文的形式发送内容,不安全。因此HTTPS为了保证这些隐私数据可以进行加密传输,让HTTP运行在SSL和TLS协议上。HTTPS=HTTP+SSL、TLS。通过SSL证书验证服务器的身份,为通信加密。
- 区别
- HTTPS是HTTP协议的安全版本。HTTP是明文的是不安全的。HTTPS使用了SSL和TLS协议进行加密处理。
- 连接方式不同,默认端口不一样。HTTP是80,HTTPS是443
- HTTP连接建立相对简单,TCP三次握手之后便可进行HTTP的报文传输,而HTTPS在三次握手之后还需要进行SSL/TLS的握手过程。由于需要设计加密和多次握手,性能方面不如HTTP
- 费用高:SSL和TLS证书需要更多成本。
HTTPS如何保证安全性的?
- SSL、TLS
- HTTPS使用了SSL和TLS协议进行加密处理。
- 安全套接字协议以及继任者传输安全。是为网络通信提供安全以及数据完整性的一种安全协议。
- 混合加密:保证数据的机密性
- 对称加密:解密和加密都是用同一个是对称的,只要保证密钥的安全就能保证整个通信过程安全
- 非对称加密:存在两个密钥,一个公钥一个私钥,两个密钥不相同,公钥是公开的私钥需要保密,公钥和私钥都可以用来加密解密,公钥只能用私钥解密,私钥只能用公钥解密。
- Https通信的过程中采用的是混合加密:对称加密加非对称加密一起使用。使用加密后的会话密钥对数据加密,这样即使数据被窃听也只能得到一串密文,没有私钥是无法得到密钥的。
- 摘要算法:保证传输数据的完整性
- 摘要算法是一种特殊的压缩算法,可以把任意长度的数据压缩成固定长度且独一无二的字符串。
- 摘要算法保证了数字摘要和原文是等价的。每个消息都有唯一摘要,收到消息后只需要计算出摘要进行对比就能够确认消息的完整性,有没有被修改过。
- 数字签名:摘要算法验证数据的完整性+签名验证身份
- 将原文的部分数据关键信息先用hash函数生成消息摘要,然后用发送方的私钥加密生成数字签名,与原文一起传送给接收者。客户端使用服务器公钥解密数字签名得到消息摘要,然后用hash函数计算原文生成摘要信息,然后比对两个信息摘要是否一致,如果一致说明数据未被篡改。
- 数字签名能够确定消息确实是由发送方签名发出的,数字签名利用私钥加密公钥解密,
- CA验证机构:保证密钥的安全性
- 防止公钥被篡改:即服务器向客户端传递公钥,有可能会被中间人伪造公钥拦截。
- 就需要第三方机构(CA),保证公钥是可信的。
- 数字认证机构是客户端和服务器双方都可以信赖的第三方机构
- CA证书包含的内容 2)公钥; 3)公司信息; 4)域名; 5)有效期; 6)指纹
Https的数据加密过程
- 采用了混合加密的方式,包括对称加密和非对称加密。用对称加密的方式传输数据,用非对称加密的方式传递对称加密的密钥。
- 具体过程:
- 客户端生成会话密钥,就是对称加密生成的密钥
- 用公钥加密这个会话密钥,然后进行传递
- 服务器使用非对称加密的私钥进行解密,拿到会话密钥
- 然后客户端和服务器就可以使用同一个会话密钥进行加密。
- 请求https网址的过程
- 发送url--解析--ip
- 服务器返回公钥证书
- 客户端验证证书的有效性,是否可信。(读取证书中的证书所有者、有效期等信息一一校验,浏览器查找操作系统中已内置的受信任的证书发布机构CA,与服务器发来的证书颁发CA对比,用于校验证书是否为合法机构颁发。
- 如果找不到,就会显示警告信息。
- 可信的话,取出颁发者CA的公钥。(利用伪随机数)生成会话密钥(加密会话),并且使用公钥加密会话密钥。发送公钥加密后的会话密钥的密文。
- 服务器用私钥解密得到会话密钥。此时双方就可以基于会话密钥传递数据了。
数字证书
- 专门用来识别通讯双方信息的一个证书,由Certificate Authority颁发。
- 防止公钥被篡改:即服务器向客户端传递公钥,有可能会被中间人伪造公钥拦截。 就需要第三方机构(CA),保证公钥是可信的。数字认证机构是客户端和服务器双方都可以信赖的第三方机构。
- 服务器从大家都信任的第三方机构申请一个身份证书,客户端建立连接之前会请求服务器申请的证书,服务器把证书发送给客户端,客户端验证身份。
- 证书的内容
- 证书的发布机构
- 证书有效期
- 公钥
- 证书所有者
- 签名
http1.0 2.0
- http1.0 浏览器和服务器之保持短暂的链接,每次请求都需要与服务器建立一个tcp连接。最终导致每个文件都包含了多次请求和响应。
- http1.1:长连接、管道化(同时发送多个请求)、缓存处理:新增了一些请求头响应头响应头、断点续传。
- 长连接引入了长连接,TCP连接默认开启长连接,可以被多个请求复用。http1.0需要使用keep-alive参数来告知服务器端要建立长连接。
- 多个请求和响应可以在同一个连接中传输同一个TCP连接,客户端可以同时发送多个请求
- 新增了一些请求头和响应头:比如引入更多的缓存控制策略:If-Unmodified-Since,If-None-Match等缓存头控制缓存策略。而Http1.0主要使用header里的If-Modified-Since,Expire来做缓存判断的标准。
- Host域:http1.0中认为每台服务器都绑定了一个唯一的IP地址,因此请求消息的URL并没有传递主机名,http1.0没有host域。随着虚拟主机发展,一台物理服务器中可以存在多个虚拟主机。httphttp1.1请求消息支持host域,没有host域会报错。实现了一台服务器,可以在同一个IP地址和端口号上使用不同的主机名创建多个web虚拟站点
- 允许客户端不用等待上一次请求的返回结果,就可以发出下一次请求虽然允许复用TCP连接,但是同一个TCP连接中,所有的数据通信必须按次序进行,服务器只有处理完一个请求才会继续处理下一个请求。如果前面的请求处理特别慢,就会引起排队
- 新增了一些请求方法:PUT,DELETE,OPTIONS
- http2.0 :二进制分帧、多路复用、首部压缩、服务器推送
- 采用了二进制而非文本格式。解析起来更加高效。
- 增加了更多多路复用的能力 实现完全多路复用。在一个连接中,客户端和浏览器都是可以同时发送请求和回应,不需要按照顺序一一对应,避免了队头堵塞。
- 首部压缩 http1.0不支持header数据的压缩,http2.0使用hpack算法对数据进行压缩,这样数据的体积小了,在网络上传输的就更快。
- 服务器推送 服务器推送是一种在客户端请求之前发送数据的机制。网页中html,样式表,脚本图片等资源,在http1.1章每一个都必须明确的请求,这是一个很慢的过程。http2.0引入server push,允许服务器推送资源给服务器,在浏览器明确的请求之前获取,客户端可以从本地加载这些资源,而不是通过网络请求。
- http3.0
- http1.1和2.0都有队头堵塞的问题
- http3.0把http下层的tcp协议改成UDP,基于udp的QUIC实现类似tcp的可靠性传输。
- http3.0具体的特性
- 连接迁移:每条TCP链接都有一条唯一标识,由源ip,源端口,目的ip,目的端口组成。源ip和源端口都比较稳定,但是目的ip和目的端口会由于网络因素发生改变,一旦改变TCP连接也会断开。而QUIC基于udp协议,每条UDO协议不再由四元组标识,而是客户端随机产生的一个64位数据作为id,只要id不变,这条udp就不会改变,因此维持连接的能力比较强。
- 没有队头堵塞。http2.0的多路复用可以解决http层的队头堵塞,但是tcp的队头堵塞依然存在,在数据包超时确认或者重传会等待重传,组测当前窗口向右滑动造成堵塞。而QUIC基于udp,即使中途发生丢包或者超时确认,后面的数据不会等待,因为全部接收完成之后可以根据ID和偏移量完成重新拼装。
- 自定义的拥塞控制
- 前向安全和前向纠错。udp不可靠,但是QUIC添加了数据纠错和校验机制:每当发送一组数据以后,就对这组数据进行异或运算,并将结果一并发出,那么接收方会有两份数据版本,因此可以对初始数据进行纠错和校验,从而保证了数据的可靠性。
http1.0、2.0、3.0的区别
- 1.0:短链接
- 1.1:
- 长连接(Http响应头中connection-keep-alive)http请求结束之后链接不会断开
- 管道化:多个请求和响应可以在同一个tcp连接中传输,且不用等待上一次的请求结果就可以发送,但是需要按顺序进行回应
- 缓存处理:新增了一些请求头和响应头:If-Modified-Since(If-Unmodified-Since)/E-tag(If-None-Match)用于缓存判断。
- 断点续传:上传数据的过程中如果遇到网络问题,导致传输中断,会在恢复后从上次传输到的位置继续传输。
- 2.0
- 二进制分帧:把http请求的消息进行二进制编码,并分成一个个二进制帧,传输更快
- 多路复用:同一个域名下的多个http请求在同一个TCP连接中,可以同时发送和响应,是一个双向数据流的概念,且不需要按照顺序进行响应
- 头部压缩:使用hpack算法对数据进行压缩,体积更小,传输更快
- 服务器推送:在客户端请求之前发送数据,(2.0之前,网页中的静态资源,html、图片等等静态资源每一个都必须有明确的请求,这样就会比较慢),http2.0之后引入server-push,允许在浏览器发送请求之前服务器向浏览器推送数据,这样在打开网页的时候,客户端就可以在本地加载资源。
- 从以上演变过程可知:http想通过减少tcp的连接,加快http的传输速度。但是http不能解决底层协议带来的限制,比如TCP连接的时耗,TCP的队头阻塞
- 3.0
- 更快:由于底层是UDP协议,UDP不需要握手建立连接,并且没有确认机制和丢包重传机制,不会重排数据报顺序,没有队首阻塞。
- 多路复用:同一域名的多条http3请求可以使用同一个QUIC连接
- 丢包重传、拥塞控制:TCP中好的特质也实现。
- 队首阻塞问题解决:单条数据流的阻塞问题,TCP中滑动窗口,必须保证窗口中的包全部都收到了才会向后滑动;但是QUIC中,窗口的移动仅仅取决于最大字节偏移,不会等待丢包重传和超时重传,而是全部接收全之后可以根据ID和偏移量进行重新拼接。多条数据流的阻塞:TCP中两个stream不相互独立,一条阻塞另一条也会阻塞,但是QUIC中两个stream完全独立。
- 链接迁移:TCP标识,根据ip地址和端口号进行识别,若因为网络因素发生改变,TCP也会断开,会重新进行连接。但是QUIC通过64位Connection ID作为标识,只要id不变就不会重新握手。
进程和线程与协程
进程
- 定义
- 进程就是一段程序的执行过程,例如启动某个app。
- 是操作系统动态执行的基本单元,是最小的资源管理单元,
- 是应用程序的启动实例,操作系统为内存创建独立的内存,存放代码和数据
- 进程的三种状态
- 就绪:进程已经准备好,只要处理器分配资源就可以马上执行
- 运行:获得处理器分配的资源,程序开始执行
- 阻塞:当程序条件不够的时候,需要等待提交满足的时候才能执行
线程
- 定义
- 线程是操作系统最小的执行单元,
- 是进程的组成部分,每个进程至少有一个线程或者多个子线程
- 现成的状态
- 就绪:线程具备运行的所有条件,逻辑上可以运行,在等待处理及
- 运行:线程占用处理机正在运行
- 阻塞:线程在等待一个事件,逻辑上不可执行
区别
- 定义不同,进程是操作系统资源分配的基本单位,线程是操作系统的最小执行单元。
- 内存空间:
- 每一个进行拥有独立的内存空间,但是所有线程共享进程中的内存空间。
- 因此线程之间可以共享进程的数据,而进程只能访问到系统分配的资源,但是可以通过IPC机制进行进程间通信。
- 因此,某个线程执行出错,会导致整个进程崩溃;而进程和进程之间是独立的隔离的,某个进程挂起或者崩溃不会影响到其他进程的运行。
- 切换开销:进程之间切换开销大,线程间切换开销小。
程序和进程的区别
程序是一个静态的指令集和,而进程是一个正在系统中活动的指令集和。 进程中有时间的概念,进程具有自己的生命周期和各种不同的状态,而程序中不具备这些概念。
协程
- 定义:协程又称微线程,协程的调度完全由用户控制(区别于进程和线程都是由操作系统进行调度)
- 一个线程可以拥有多个协程,可以暂停运行,可以在挂起点恢复
- 开销小,占用内存少
- 但是本质上是单线程,无法利用多核资源、阻塞时会阻塞整个程序。
并发和并行
- 并发:在操作系统中,某一个时间段,几个程序在同一个CPU上运行(但是任意一个时间点上,只有一个程序在CPU上运行)。当有多个线程时,如果系统只有一个CPU,那么CPU不可能真正的同时进行
- 并行:两个线程不抢占CPU资源,可以同时运行。