网络相关
零碎不系统,仅供参考,不能保证精准度和时效性
从输入 URL 到页面呈现出来的过程
TCP 的三次握手和四次挥手
...
~~~~~~~ 基础知识 ~~~~~~
URL 和 URI 的区别
URI: Uniform Resource Identifier, 统一资源标识符
用唯一的标识来确定一个资源,是一种抽象的定义
即不管用什么方法来定义,只要能唯一地标识一个资源,就可以称为 URI
URL 和 URN 是 URI 的子集。
URL: Uniform Resource Location, 统一资源定位符
可以理解为使用地址来标识资源
URN: Uniform Resource Name, 统一资源名称
跨域
同源 vs 跨域
origin: 协议+域名+端口
同源策略的限制 (???)
cookie, localStorage, IndexDB 无法读取
DOM 和 JS 对象无法获得
AJAX 请求不能发送
跨域解决方案
JSONP, postMessage
CORS
document.domain
....
P20
跨域,是指浏览器不能执行其它网站的脚本。它是由浏览器的同源策略造成的,是浏览器对 JavaScript 实施的安全限制,那么只要协议、域名、端口有任何一个不同,都被当作是不同的域。 跨域原理,即是通过各种方式,避开浏览器的安全限制。
JS 实现跨域的方法,https://segmentfault.com/a/1190000011145364
JSONP
JSONP 能实现跨域,它是利用标签不受同源策略限制的特性(这算是一个漏洞)。
浏览器用 JavaScript 代码动态创建一个
<script>
标签,其src
属性引用第三方的 API 地址,并提供一个回调函数的 function name比如 https://www.smartstudy.com/api/?callback=functionName
其中的 query 都是约定好了,比如
callback
和functionName
后端通过 query 取到函数名,然后把需要的数据以参数的形式传递给该函数,返回给浏览器
浏览器解析服务器返回的数据,执行该回调函数
JSONP 并不使用 XMLHttpRequest 对象加载数据,而是通过 <script>
标签把资源当做普通的 JavaScript 脚本来加载,所以不存在跨域的问题,也不是真正的 AJAX。
CORS vs JSONP
CORS 可以用作 JSONP 模式的现代替代方案:
JSONP 仅支持 GET 方法,而 CORS 还支持其它类型的 HTTP 请求
CORS 让程序员可以使用常规的 XMLHttpRequest,它支持比 JSONP 更好的错误处理
JSONP 可能会导致跨站点脚本 XSS 问题(在外部站点受到威胁时),而 CORS 允许网站手动解析响应以提高安全性
JSONP 的主要优点是兼容 CORS 出现之前的老版浏览器。现在大多数现代 Web 浏览器都支持 CORS。
客户端存储
cookie, sessionStorage, localStorage, indexdDB
共同点:都保存在浏览器端,且都是同源的
是否在 HTTP 中携带
cookie 数据会始终在同源的 HTTP 请求中携带(即使不需要),即在浏览器和服务器之间来回传递
所以它的容量较小,大约 4K 左右
所以只适合保存很小的数据,比如会话标识
初衷就是为了弥补 HTTP 的无状态
sessionStorage 和 localStorage 仅在本地保存,不参与和服务器的通信
是否持久化保存
cookie:在设置的 cookie 过期时间之前一直有效(即使窗口或浏览器关闭了),否则默认为关闭浏览器后失效
cookie 还可以限制只属于某个 path 下
sessionStorage:仅在当前“浏览器”窗口关闭前有效(不持久)
session,会话,两个页签打开同一个页面,也被视为同一个会话
localStorage:持久化存储(即使窗口或浏览器关闭了),除非被手动清除
存储空间
cookie,4K 左右
sessionstorage 和 localStorage,5M 左右
易用性
cookie 原生的接口不太友好,需要自己封装
其它:可采用原生接口,也可自己封装
应用场景
cookie
Web 性能优化
检测页面的加载时间,一般有两种方式:
被动去测:在被检测的页面置入脚本或探针,当用户访问网页时,探针自动采集数据并传回数据库进行分析(数据更真实)
主动监测:主动搭建分布式受控环境,模拟用户发起页面访问请求,主动采集性能数据并分析。在检测的精准度上,专业的第三方工具效果更佳,比如说性能极客
优化手段:
内存溢出
降低请求量:合并资源,减少 HTTP 请求数,minify/gzip 压缩,webP,lazyLoad
加快请求速度:预解析 DNS,减少域名数,并行加载,CDN 分发,避免重定向
缓存:HTTP 协议缓存请求,离线缓存 manifest,离线数据缓存 localStorage
渲染:JS/CSS 优化,动画绘制频率,加载顺序,服务端渲染,pipeline
~~~~~~ HTTP 相关 ~~~~~
HTTP 请求的方法
最常见:
GET
从指定的资源请求数据POST
向指定的资源提交要被处理的数据
次常见:
HEAD
:类似于 GET 请求,只是返回的响应中没有具体内容,客户端读取响应的 HeadersOPTIONS
:允许客户端查看服务器的性能,比如服务器支持的请求方式等
不太常见的:
PUT
DELETE
TRACE
CONNECT
get 和 post 的区别
GET vs POST
参数位置:在 URL 里 vs 在 request body 中
只能 URL 编码 vs 多种编码方式
GET 的参数有长度限制,而 POST 没有
一般限制在 2~8K 之间,常见的是 1K 之内
POST 的参数更安全,所以更适合传递一些敏感信息
浏览器的不同处理
GET 请求会被浏览器主动 cache
GET 请求参数会被完整地保留在浏览历史记录里
TCP 数据包
GET 请求产生一个 TCP 数据包
浏览器会把 HTTP Header 和 data 一起发出去,服务器响应 200
POST 产生两个 TCP 数据包
浏览器先发送 header,服务器响应 100 continue
浏览器再发送 data,服务器响应 200 ok
GET 和 POST 的底层都是 TCP/IP,都是 TCP 连接,并无差别。只是由于 HTTP 的规定以及浏览器和服务器的限制,导致它们在使用上有些不同。
get 请求传参长度的误区
误区:我们常说 get 请求参数的大小存在限制,而 post 请求的参数大小是无限制的。
HTTP 协议从未规定 get 和 post 请求的长度限制
而是浏览器和 web 服务器限制了 get 请求的参数长度
不同的浏览器和 web 服务器,限制的最大长度不一样
要支持 IE,则最大长度为 2083byte
若只支持 Chrome,则最大长度 8182byte
HTTP Header
可以将 HTTP Header 分为:
通用首部:表示一些通用信息。比如:
date
表示报文创建时间
请求首部:请求报文中独有的。比如:
cookie 相关的
if-Modified-Since
响应首部:响应报文中独有的。比如:
set-cookie
location
重定向相关
实体首部:用来描述实体部分。比如:
allow
用来描述可执行的请求方法content-type
描述主题类型content-Encoding
描述主体的编码方式
一个 TCP 连接能发几个 HTTP 请求?
HTTP 1.0,一个 TCP 发送一个 HTTP 请求
一般情况,不支持长连接,在每次请求发送完毕之后 TCP 连接会立即断开
在请求头带上
Connection: Keep-Alive
也可以发送多条,不过有限制
HTTP 1.1,支持长连接,所以只要 TCP 连接不断开,就可以一直发送 HTTP 请求,没有上限
HTTP 2.0
支持长连接。所以只要 TCP 连接不断开,就可以一直发送 HTTP 请求,没有上线
支持多路复用,所以一个 TCP 连接可以并发多个 HTTP 请求
TCP 和 UDP
TCP 是面向连接的可靠性传输,而 UDP 是不可靠的。
TCP vs UDP
面向连接的 vs 无连接的(发送数据前不需要先建立链接)
提供可靠服务 vs 尽最大努力交付(不保证可靠交付)
通过 TCP 连接传送的数据,无差错、不丢失、不重复、且按序到达
UDP 即便出现网络拥塞也不会降低发送速率,所以会丢包
比如实时应用(电话和视频会议)
面向字节流 vs 面向报文
只能是 1 对 1 的 vs 支持 1 对 1, 1 对多
首部大小:20 字节 vs 只有 8 字节
WebSocket 的实现和应用
WebSocket 是 HTML5 中的协议,支持持久性连接。
HTTP 1.0 和 HTTP 1.1 都不支持持久性的连接
HTTP 1.1 中的
keep-alive
可以将多个 HTTP 请求合并为一个。
HTTP 的生命周期通过 Request-Response 来界定。一个 Request 只能对应一个 Response,而且这个 Response 是被动的,不能主动发起。
在 HTTP 1.0 协议中,这次 HTTP 请求就结束了
在 HTTP 1.1 中,
connection: Keep-alive
,就可以在一个 HTTP 连接中,发送多个 Request,接收多个 Response
WebSocket 是基于 HTTP 协议的,或者说借用了 HTTP 协议来完成一部分握手,在握手阶段和 HTTP 是相同的。
看一个 websocket 握手协议的实现,基本是 2 个属性 upgrade
, connection
。
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
websocket 和 ajax 轮询
websocket,HTML5 的新协议,可以实现服务端和服务器的通信,实现服务器的推送功能
优点:只要建立一次连接,就可以连续不断地得到服务器推送的消息,因此节省带宽、减少服务器端的压力
ajax 轮询:每隔一段时间(0.5s)就向服务器发起 ajax 请求,以查询服务器是否有数据更新
缺点:每次都要建立 HTTP 连接,因此比较浪费带
HTTP 协议(特征)
基于 TCP/IP 通信协议来传递数据,比如 HTML 文件、图片文件、查询结果
属于应用层的、面向对象的协议
使用简捷、快速,适用于分布式超媒体信息系统
它于 1990 年提出,经过几年的使用与发展,得到不断地完善和扩展
目前在 WWW 中使用的是 HTTP/1.0 的第六版
HTTP/1.1 的规范化工作正在进行之中
HTTP-NG(Next Generation of HTTP)的建议已经提出
HTTP 协议工作于客户端-服务端架构中
浏览器作为 HTTP 客户端,通过 URL 向 HTTP 服务端(WEB 服务器)发送请求
Web 服务器根据接收到的请求后,向客户端发送响应信息
HTTP 和 HTTPS 的区别
HTTP,超文本传输协议。基于 TCP/IP 通信协议,用于从 WWW 服务器传输超文本到本地浏览器,它的模式是“一个请求对应一个响应”。
HTTPS 是 HTTP 的安全版,即在 HTTP 下加入 SSL 层。SSL 是 HTTPS 的安全基础,因为 HTTP 传输的数据是明文的(没有加密),而 SSL 协议可以对其数据进行加密。SSL 加密是在传输层实现的。
所以说,HTTPS 比 HTTP 协议的安全性更高,它能进行加密传输和身份认证。
SSL 加密
CA 证书
此外,HTTP 80端口 vs HTTPS 443端口
HTTPS 的原理和优缺点
工作原理
客户端使用 HTTPS URL 访问服务器
服务器建立 SSL 链接,并将网站的证书(包含了公钥)传给客户端
客户端和服务器端开始协商 SSL 链接的安全等级,并建立会话密钥
然后通过网站的公钥来加密会话密钥并传送给网站
优点
可以认证用户和服务器,确保数据发送到正确的客户机和服务器
更安全,可防止数据在传输过程中被窃取、改变
是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本
缺点
握手阶段比较费时,会使页面加载时间延长 50%,增加 10%~20%的耗电
缓存不如 HTTP 高效,会增加数据开销
SSL 证书需要钱,功能越强大的证书费用越高
SSL 证书需要绑定 IP,不能在同一个 IP 上绑定多个域名,ipv4 资源支持不了这种消耗
HTTP 2.0
HTTP 2.0 是基于 HTTPS 的,天然具有安全特性,且它还能避免单纯使用 HTTPS 的性能下降。
提升访问速度:HTTP 1.0,请求资源所需时间更少、访问速度更快
多路复用:这相当于是长连接的增强
每个 Request 请求可以随机地混杂在一起,接收方可以根据 Request 的 id 将 Request 再归属到各自不同的服务端请求里面
另外多路复用中也支持了流的优先级,允许客户端告诉服务器那些内容是更优先级的资源,可以优先传输。
在 HTTP 1.1 中,客户端在同一时间针对同一域名下的请求,有数量限制(连接数量),超过限制了会被阻塞
二进制分帧:
HTTP 1.X 的解析是基于文本的
HTTP 2.0 将所有的传输信息分割为更小的消息和帧,并对它们采用二进制格式编码
基于二进制可以让协议有更多的扩展性,比如用“帧”来传输数据和指令
首部压缩
服务器端推送
cookie, session 区别
HTTP 是一个无状态协议,cookie 的最大作用就是存储
sessionId 用来唯一标识用户
cookie 和 session 都可以用来存储用户信息。
位置不同
cookie 存放在客户端(约4K),服务端和客户端都可以设置
session 存放在服务器端,可以存文件/数据库/内存中
安全性:cookie < session
可以通过分析存放在本地的 cookie 并进行 cookie 欺骗,不安全
敏感信息通常用 session 存储,比如用户登录信息
性能:cookie > session
session 会在一定时间内保存在服务器上,当访问增多,会比较占用服务器的性能
存储大小
单个 cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 cookie
~~~~~~~~ 缓存 ~~~~~~~~
缓存机制的 4 个方面
作用:减少网络 IO 消耗,提高访问速度。
浏览器的缓存机制有四个方面,按照获取资源时请求的优先级,依次排列如下:
Memory Cache
Service Worker Cache
HTTP Cache
Push Cache
强缓存、协商缓存
根据响应的 Header 内容来决定:
强缓存:
200
from cache,不发请求到服务器,直接从缓存取过去用
expires
,使用的是基于服务器端的绝对时间(会存在时差)现在用
Cache-Control
,使用相对时间是一个通用 Header 字段,可用于 HTTP 请求和响应中
该缓存指令是单向的,常见的取值有
private
默认no-cache
max-age
must-revalidate
若两同时存在,则用新的
协商缓存:
304
not modified,发送请求到服务器,通过服务器告知缓存是否可用Last-Modified
时间戳Last-Modified/If-Modified-Since
Etag/If-None-Match
在没有命中强缓存的时候,才会走协商缓存。
预期:如果服务器上的资源更新了,那浏览器就请求新资源;否则就用本地缓存。以最大程度地减少因网络请求而产生的资源浪费。
在请求这些有设置缓存的数据时,会先查看是否过期
如果没有过期,则直接使用本地缓存
否则,就向服务器发起请求,并重新协商有关缓存信息
如果上次响应设置了
ETag
值,则会在这次请求的时候作为If-None-Match
的值交给服务器校验如果上次响应设置了
Last-Modified
值,则会在这次请求的时候作为If-Modified-Since
的值交给服务器校验如果都没有设置,则直接请求
而在需要“服务器校验(协商缓存)”时,它会返回
200
或304
200
表示这是全新的数据304
表示从缓存取
说明:两次“从缓存取”,第一次是命中强缓存,第二次是经过与服务器协商且确认缓存未过期。
cookie 可以设置的字段
name
cookie 的名称value
cookie 的值domain
为可以访问此 cookie 的域名顶级域名
只能设置
domain
为顶级域名,不能设置为二级域名或者三级域名,否则 cookie 无法生成只能获取到
domain
设置为顶级域名的 cookie,其他 domain 设置为二级域名的无法获取
二级域名能读取设置了
domain
为顶级域名或者自身的 cookie,但不能读取其他二级域名domain
的 cookie所以要想 cookie 在多个二级域名中共享,需要设置 domain 为顶级域名,这样就可以在所有二级域名里面或者到这个 cookie 的值了
非顶级域名(如二级域名或者三级域名)设置的 cookie 的
domain
只能为顶级域名或二级域名或三级域名本身,不能设置其他二级域名的 cookie,否则 cookie 无法生成
path
为可以访问此 cookie 的页面路径比如 domain 是 abc.com,path 是/test,那么只 有/test 路径下的页面可以读取此 cookie。
expires/Max-Age
为此 cookie 过期时间若设置其值为一个时间,那么当到达此时间后,此 cookie 失效
不设置的话默认值是 Session,意思是 cookie 会和 session 一起失效。当浏览器关闭(不是浏览器标签页,而是整个浏览器) 后,此 cookie 失效
Size
此 cookie 大小http
cookie 的httponly
属性若此属性为 true,则只有在 HTTP 请求头中会带有此 cookie 的信息,而不能通过
document.cookie
来访问此 cookie。
secure
设置是否只能通过 HTTPS 来传递此条 cookie
cookie 的弊端
安全性
若被拦截了,就能得到相关的 session 信息
甚至不需要解密,原样转发就能达到目的
有数量和长度的限制
每个 domain 最多 20 条 cookie
每个 cookie 最大长度 4KB
场景有限。比如
ajax 解决浏览器缓存问题
在 ajax 发送请求前加上
anyAjaxObj.setRequestHeader("If-Modified-Since","0")
在 ajax 发送请求前加上
anyAjaxObj.setRequestHeader("Cache-Control","no-cache")
在 URL 后面加上一个随机数:
"fresh=" + Math.random()
在 URL 后面加上时间戳
"nowtime=" + new Date().getTime()
如果是使用 jQuery,直接这样就可以了 $.ajaxSetup({cache:false})
,这样页面的所有 ajax 都会执行这条语句就是不需要保存缓存记录。
~~~~~~~~ 更多 ~~~~~~~~
Fetch 发送两次请求的原因
Fetch 发送 POST 请求时,总是发送两次:第一次状态码是 204,第二次才成功。
原因:Fetch 第一次会发送一个 Options 请求,询问服务器是否支持修改的请求头,如果服务器支持,则会在第二次发送真正的请求
CDN
CDN,Content Delivery Network,内容分发网络。
CDN 是一个智能虚拟网络,构建在现有网络的基础之上的。它依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,让用户就近获取所需内容,从而降低网络阻塞、提高用户访问响应速度和命中率。CDN 的关键技术主要:内容存储和分发技术。
CDN 的主要功能:
节省骨干网带宽,减少带宽请求量
提供服务器端加速,避免由于用户访问量大而造成服务器过载
服务商使用 web cach 技术,在本地缓存“用户访问过的 web 页面和对象”
既避免了占用主干的出口带宽
又能缩短用户访问页面的响应时间
能克服网站分布不均的问题,并且能降低网站自身建设和维护成本
降低“通信风暴”的影响,从而提高网络访问的稳定性
CDN 的基本原理是:广泛采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络中,在用户访问网站的时候,利用“全局负载技术”将用户的访问指向距离最近、且工作正常的缓存服务器上,由缓存服务器直接响应用户的请求。
Last updated