疫情虽然没有结束,不过学习始终是不能停的。这次的内容主要以网络为主,也是依据正常面试中常被问及的话题进行了梳理
每个点都没有过分的深究,也是为了文章字数不要太过庞大考虑的,点到为止,是这次的主题
那么,让我们闲言少叙,开始进入主题吧!!!
http
http1.1和http2.0
如果要说http1.1和http2.0的区别,那就先要说http1.1和兄弟http1.0的区别了
现在我们常用的http协议也是http1.1这个版本的
http1.1支持
- 长链接,默认是
Connection: keep-alive
- 减少了TCP建立和关闭连接的消耗和延迟,一次建立多次请求和响应
- 缓存处理
- http1.0使用头部的
Expires
和Pragma
来控制缓存 - http1.1里支持了更多的缓存策略,
Etag、If-Modified-Since、If-Unmodified-Since、If-Match、If-None-Match、Cache-Control
- http1.0使用头部的
- Host头处理
- 同一台机器上,可能部署多个app,通过解析host+端口,指定具体访问站点
好了,知道了现在市面上最广泛的协议都可以做什么,那么就再来看看http2.0这个时隔了16年的小朋友都有哪些过人之处吧!!!
其实与其说http2.0的过人之处,不如说它是在优化http1.1上的不足
下面写的都是在改善以前的缺点,一起看看吧
http2.0支持
头部压缩
头太大,太重,晕晕的,需要减负
-
体积压缩
- 所以http2.0采用了HPACK算法压缩了header的大小
-
缓存header
- 对传输过的header进行缓存,如果有传输过header的键名,就不再重复发送了,减少了传输的大小
多路复用
解决了什么问题?
答: 浏览器限制同一个域名下请求的数量,(chrome好像是6个)
多路复用的大致意思就是
- 在一个TCP连接中可以同时发送多个请求,避免线头阻塞问题,极大的提高传输性能
服务端推送
就是服务端主动的把你必定需要的资源推送给你,让你在请求一次的情况下得到多个响应数据
举个栗子,比如你访问了首页,服务器就会主动的把首页的css,js,图片
等资源都主动推送过去,毕竟这些都是必须的资源
好了,http1.1和http2.0版本之间的不同就简简单单的写到这里吧,由于本人也不是科班出身,对这种计算机网络知识实在匮乏,就先点到为止吧,下面继续看其他的
http和https的区别
其实谈及二者的区别,也是在告诉大家http有哪些不安全因素
那么我们来看看不安全的点都有哪些吧
之后你就会明白https的出现到底多么有意义了
不安全的http
- 信息被窃听
- http的报文是使用明文方式发送
- 认证问题
- 通信双方在请求和响应时无法确认
- 劫持数据
- 请求和响应的传输过程中,容易被运营商劫持,篡改数据,无法保护数据的完整性
https够安全
https的端口是443,它基于http协议,通过ssl
或tls
提供加密处理数据、验证对方身份以及数据完整性保护的
https是在http(应用层)和tcp(传输层)之间加了一层ssl协议,来进行加密,从而变成了我们所知的https
组成部分: https = http + ssl/tls
下面我们就简单聊聊ssl/tls
协议
ssl和tls
ssl/tls
用来处理信息加密、完整性校验、身份验证
ssl/tls
基于三类算法实现
- 对称加密 -> 信息加密
- 我们拥有同一把钥匙来开门(客户端|服务端有相同的钥匙),别人没钥匙开不开
- 非对称加密 -> 身份验证密钥协商
- 我们都能进饭店吃饭(公钥),但是收银台的钥匙(私钥)只有老板有
- 散列算法 -> 完整校验
- 只有你自己的指纹(加密)可以解锁门锁
连接过程
- 首先建立tcp握手连接
- 进行ssl协议的握手密钥交换
- 通过共同约定的密钥开始通信
通过以上内容的了解,https是网站安全的代言人,尽快的都使用上https协议吧
http报文头部有哪些字段?有什么意义?
通用头字段
字段名 | 常见值 | 意义 |
---|---|---|
Connection | keep-alive | 链接的管理 |
Cache-Control | max-age=xxx秒 | 控制缓存行为 |
Date | 日期和时间 | 报文日期 |
Transfer-Encoding | chunked | 报文主体的传输编码方式 |
请求头字段
字段名 | 常见值 | 意义 |
---|---|---|
Accept | * / * | 处理的媒体类型 |
Accept-Encoding | gzip | 编码类型 |
Accept-Langulage | zh-CN,zh | 编码语言 |
Host | 域名或IP | 指定具体访问站点 |
If-Modified-Since | 日期和时间 | 比较资源更新的时间 |
If-None-Match | Etag戳 | 比较实体标记 |
Referer | 域名或IP | 请求来源 |
User-Agent | 浏览器版本信息 | 用户代理 |
响应头字段
字段名 | 常见值 | 意义 |
---|---|---|
Content-Encoding | gzip | 主体编码类型 |
Content-Type | application/json或text/css等 | 主体媒体类型 |
Expires | 日期和时间 | 过期时间 |
Last-Modified | 日期和时间 | 最后修改时间 |
Etag | Etag戳 | 资源匹配信息 |
http响应状态码
状态码想必是经常见到的东西了,这里要是展开说的话也会有很多内容的,
不过我们依然从头开始,梳理一下常见的状态码以及使用情况
状态码总共分为5个大类
- 1xx: 信息类状态码(属于准备阶段)
- 2xx: 成功状态码
- 3xx: 重定向状态码
- 4xx: 客户端错误状态码
- 5xx: 服务端错误状态码
各大类中常见的状态码
每个大类中都有我们常见的状态码,不多不少,我们都有过照面,这就足够了
2xx - 成功系列
- 200 - 请求成功
- 204 - 返回响应头,不带响应体(如:打点请求)
- 206 - 返回部分数据(如:断点续传)
3xx - 重定向系列
- 301 - 永久重定向
- 302 - 临时重定向
- 303 - 只能用get请求的临时重定向
- 304 - 没有更改(主要用来处理缓存)
- 307 - 不改变请求方法的临时重定向
4xx - 客户端错误系列
- 400 - 请求报文语法错误
- 401 - 需要认证
- 403 - 拒绝访问资源
- 404 - 文件不存在
5xx - 服务器错误系列
- 500 - 服务器故障
- 503 - 服务器宕机了
大概就把关于http部分的内容先说到这里吧,下面我们来说一下老生常谈的话题:缓存,缓存的作用想必不用说也知道(减少数据传输,提高网页速度),所以我们就直奔主题进入缓存吧
缓存
缓存主要分为两种,一种是强制缓存,另一种就是协商缓存了(304其实就是协商缓存)
强制缓存
强制缓存通常是用在图片或者logo这样长久不会更改的资源上的
当第一次访问资源的时候,会正常拿到200的状态码
当第二次访问资源的时候,就会去浏览器的缓存里找缓存文件使用了,不过返回的状态码仍然是200
强制缓存主要是通过Cache-Control
和Expires
来设置的
Cache-Control
通过在服务端设置响应头来添加Cache-Control
如: Cache-Control: max-age=100
max-age
是一个相对时间,单位是秒
上面那行表示强制缓存100秒内不再去服务器拿资源,而是直接使用浏览器的缓存里的文件
Expires
Expires可以说是很早就有了,之所以设置强缓存的时候还设置它也是为了兼容低版本
如: Expires: new Date(+new Date + 20 * 1000).toUTCString()
Expires接收的是绝对时间,单位是毫秒,并且要转成格林威治时间,以前的toGMTString()
已经废弃了,现在统一用toUTCString()
优先级
由于Expires是一种向下兼容的方式,所以如果同时有Cache-Control
和Expires
被设置的情况下,强缓存会只认Cache-Control
ok,说完了强制缓存,就轮到协商缓存登场了,对于协商缓存来说也经常是考点之一
协商缓存
还是一样的套路
当第一次访问资源的时候,会正常拿到200的状态码,服务端会把缓存标识和数据一起返回
当第二次访问资源的时候,就会把缓存标识发给服务端,服务端去校验是否匹配,匹配成功就返回304,直接使用缓存即可
协商缓存常见的也是两种,一种是Last-Modified,另一种是Etag
先从Last-Modified说起吧
Last-Modifed
Last-Modified
从单词的大意可以看出,表示的是最后修改时间
客户端访问资源,服务端会设置一个响应头为Last-Modified
并且把值设置为绝对时间
这样客户端再访问同一个资源的时候,请求头上会带有一个If-Modified-Since
的字段
关键点:
服务端会通过客户端发来的If-Modified-Since
和Last-Modified
的值比较
- 相同: 返回304状态码,使用缓存文件
- 不相同: 返回200状态码,请求资源
缺点:
- 时间不精确,如果最后修改时间变了,可是内容没有变就失效了
- 举个例子:
- 比如我5秒前改了个值,刷新请求返回200
- 然后我又撤销了刚才改的代码,再刷新请求又返回200
- 但是其实我的内容没有改变,只是根据我修改的时间来判断,就不太准了
解决这个问题并不难,直接把下一位主角请上来
Etag
ETag
是实体标签的缩写,根据实体内容生成的一个hash戳
,只有内容改变了Etag
才变
流程一样,还是客户端第一次访问资源时,服务端会把Etag
和数据一起返回
再次访问资源时,请求头就会有个If-None-Match
字段并且也会发送给服务端
一样的关键点:
服务端会通过客户端发来的If-None-Match
和Etag
的值比较
- 相同: 返回304状态码,使用缓存文件
- 不相同: 返回200状态码,请求资源
强制不缓存
曾经有道题目问的是不缓存有哪些方式?
其实很简单,只要在设置Cache-Control: no-store
就可以了
但是很多人也都见过no-cache
这个值,实际上它依然会缓存但是每次都像服务器发请求罢了
跨域
跨域是前端同学见怪不怪的问题了,浏览器本着安全的原则采用了同源策略
要求只有域名、协议、端口号`都相同的才可以进行请求
概念的东西,我就不啰嗦了,下面直接开始说跨域的几种方式吧
- jsonp
- 通过script的src来进行跨域请求,把数据包在一个函数内传递过来
优点:使用简单、兼容性好
缺点:只支持get请求,不够安全有XSS攻击的危险
- cors
-
发送请求时会附带一个Origin头部包含请求页面的源信息(协议、域名、端口号)
-
服务端根据头信息来进行处理,如果接受就在
Access-Control-Allow-Origin
头部回发相同的源信息实现跨域
-
优点:使用方便
缺点:浏览器兼容问题,修改主要在后端
- postMessage
- 两个页面(窗口)之间的通信,可以和内嵌的iframe通信
iframe.contentWindow.postMessage(数据, 目标域名)
优点:H5提供的API,使用方便
缺点:浏览器兼容问题,而且需要依赖iframe
- window.name
- name属性在不同的页面也存在
简单用法:
在localhost:8000/2.html
页面中添加数据到window.name,看下面代码
// 这是http://localhost:8000/2.html页面
<script>
let list = [1,2,3,4,5];
// 由于window.name内部调用了toString方法
// 所以如果你想要得到你想要的数据类型,就需要先进行JSON.stringify
window.name = JSON.stringify(list);
</script>
现在localhost:9000/1.html
想拿到上面的数据,就需要借助window.name来取了
// 这是http://localhost:9000/1.html页面
<body>
<div>我是1页面,里面有嵌套页面</div>
<iframe src="http://localhost:8000/2.html" id="f" onload="load()"></iframe>
<script>
let flag = true;
function load() {
if (flag) {
// 页面第一次加载完成就把iframe的src修改为同域下的3.html页面
f.src = 'http://localhost:9000/3.html';
flag = false;
} else {
// 之后再加载新的src的时候就可以拿到window.name上挂载的数据了
const data = JSON.parse(f.contentWindow.name);
console.log(data); // [1,2,3,4,5]
}
}
</script>
</body>
优点:挂到window.name上写法很简单
缺点:依赖iframe,且挂载到window.name上不安全
- domain
- 二级页面通过
document.domain
设置相同的域名,强制实现了同域
- 二级页面通过
优点:设置方便
缺点:依赖iframe,只支持一级和二级域名
- webSocket
- 双工通信,没有跨域限制,需要前后端建立websocket连接,开始通信
优点:H5的API,用法简单
缺点:兼容问题,需要后端提供ws服务
网络安全
XSS
用户输入的内容可能会有恶意代码
所以,一句话就是转义用户输入的内容,转义转义转义(encodeURICompoent)
// 转义html里的字符
function encodeHtml(str) {
return str.replace(/&/g, '&').
replace(/"/g, '"').
replace(/'/g, '&apos').
replace(/</g, '<').
replace(/>/g, '>')
}
CSRF
跨站请求伪造,如:钓鱼网站
- 验证码校验
- express可以用个svg-captcha生成验证码,后台进行校验
- 判断来源 referer
- 请求头里的referer判断来源,不一致的不处理
- token
- 钓鱼网站不能拿到cookie,可以通过cookie+标识符发给服务端,让服务端去匹配发送的token是否一致
- 在登录后服务端会返回token,前后端拿着token进行匹配,一样的就可以
TCP
我们知道tcp是在七层网络模型中的传输层,对于tcp的内容来讲,大多数感兴趣的都在它的那三次握手和四次挥手上了
那么我们也简单的说说看是怎么回事吧
三次握手
为什么要三次握手?
答: 为的是同步连接双方的确认号和序列号,并且交换tcp窗口大小信息
一句话:保证双方收发都没问题
握手过程如下:
- 建立连接
- 服务端收到客户端发的SYN报文,确认序列号(SYN)并发送确认号(ACK)
- 客户端收到服务端发的SYN+ACK报文,发送确认号(ACK),完成握手
四次挥手
为什么要四次挥手?
一句话:双方数据都发送完毕了,都觉得可以断开了
挥手过程如下:
- 客户端向服务端发送结束号(FIN)报文,请求关闭连接
- 服务端收到FIN报文,返回ACK报文,等待关闭
- 服务端看看数据发完没有,直到数据都发完了,再返回FIN报文,请求关闭连接
- 客户端收到FIN报文,发送ACK报文让服务端关闭连接,等一会看服务端没反应了,自己也关闭连接
更直白的过程:
- 客户端: 我要关闭连接了
- 服务端: 好的,稍等
- 服务端: 数据都给你了,可以关了
- 客户端: 你关了,我就关
当然还有个总被提及的问题
- 为什么握手是三次,但挥手却是四次?
其实从上面直白的挥手过程就能发现
多了一次就是在“好的,稍等”那次,哈哈
CDN的作用
cdn想必工作中都有用到,概念什么的就不再赘述了,总结了它的3点作用,毕竟我们不用太深入了解它的工作原理,知道作用就行了
- 缓存
- 节省服务器流量
- 最近节点优先
在浏览器地址栏输入URL,回车后发生了什么
这种问题在回答方面可大可小,可深可浅,大致流程还是亘古不变的,只不过要看是不是想深究其因了
下面我就写出来,我个人认为的过程吧
- DNS将URL解析为IP
- 有缓存,直接返回缓存
- 无缓存,继续递归解析
- DNS解析得到服务器的IP,与服务器建立TCP连接
- IP协议:选择传输路线,负责找到
- TCP协议:三次握手、分片、可靠传输、重新发送的机制
- 浏览器通过http协议发送请求
- 请求行、请求头、请求体
- 服务器接收请求后,开始查库,读文件,拼接要返回的http响应
- 浏览器收到html文件开始渲染
- 解析html为dom树,解析css为css-tree,最终生成render-tree渲染树,阻塞渲染
- 遍历渲染树开始布局,计算每个节点的大小位置信息
- 将渲染树每个节点绘制到页面上
- 加载js文件,执行js脚本
- 回流reflow和重绘repaint
就这么10条吧,其实每一条都有可以深入展开的内容,不过我这里就不一一介绍了,毕竟我也知道的甚少,就不装腔作势了,哈哈
点到为止
对于网络方面的知识我并不熟悉,也是在学习一点点的皮毛,分享给大家也是为了和大家一起进步
好了,就写到这里吧,感谢大家的观看了,886