这有一份网络相关的消息,请查收

2,177 阅读15分钟

疫情虽然没有结束,不过学习始终是不能停的。这次的内容主要以网络为主,也是依据正常面试中常被问及的话题进行了梳理

每个点都没有过分的深究,也是为了文章字数不要太过庞大考虑的,点到为止,是这次的主题

那么,让我们闲言少叙,开始进入主题吧!!!

http

http1.1和http2.0

如果要说http1.1和http2.0的区别,那就先要说http1.1和兄弟http1.0的区别了

现在我们常用的http协议也是http1.1这个版本的

http1.1支持

  1. 长链接,默认是Connection: keep-alive
    • 减少了TCP建立和关闭连接的消耗和延迟,一次建立多次请求和响应
  2. 缓存处理
    • http1.0使用头部的ExpiresPragma来控制缓存
    • http1.1里支持了更多的缓存策略,Etag、If-Modified-Since、If-Unmodified-Since、If-Match、If-None-Match、Cache-Control
  3. 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

  1. 信息被窃听
    • http的报文是使用明文方式发送
  2. 认证问题
    • 通信双方在请求和响应时无法确认
  3. 劫持数据
    • 请求和响应的传输过程中,容易被运营商劫持,篡改数据,无法保护数据的完整性

https够安全

https的端口是443,它基于http协议,通过ssltls提供加密处理数据、验证对方身份以及数据完整性保护的

https是在http(应用层)和tcp(传输层)之间加了一层ssl协议,来进行加密,从而变成了我们所知的https

组成部分: https = http + ssl/tls

下面我们就简单聊聊ssl/tls协议

ssl和tls

ssl/tls用来处理信息加密完整性校验身份验证

ssl/tls基于三类算法实现

  1. 对称加密 -> 信息加密
    • 我们拥有同一把钥匙来开门(客户端|服务端有相同的钥匙),别人没钥匙开不开
  2. 非对称加密 -> 身份验证密钥协商
    • 我们都能进饭店吃饭(公钥),但是收银台的钥匙(私钥)只有老板有
  3. 散列算法 -> 完整校验
    • 只有你自己的指纹(加密)可以解锁门锁

连接过程

  • 首先建立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-ControlExpires来设置的

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-ControlExpires被设置的情况下,强缓存会只认Cache-Control

ok,说完了强制缓存,就轮到协商缓存登场了,对于协商缓存来说也经常是考点之一

协商缓存

还是一样的套路

当第一次访问资源的时候,会正常拿到200的状态码,服务端会把缓存标识和数据一起返回

当第二次访问资源的时候,就会把缓存标识发给服务端,服务端去校验是否匹配,匹配成功就返回304,直接使用缓存即可

协商缓存常见的也是两种,一种是Last-Modified,另一种是Etag

先从Last-Modified说起吧

Last-Modifed

Last-Modified从单词的大意可以看出,表示的是最后修改时间

客户端访问资源,服务端会设置一个响应头为Last-Modified并且把值设置为绝对时间

这样客户端再访问同一个资源的时候,请求头上会带有一个If-Modified-Since的字段

关键点

服务端会通过客户端发来的If-Modified-SinceLast-Modified的值比较

  • 相同: 返回304状态码,使用缓存文件
  • 不相同: 返回200状态码,请求资源

缺点

  • 时间不精确,如果最后修改时间变了,可是内容没有变就失效了
  • 举个例子:
    • 比如我5秒前改了个值,刷新请求返回200
    • 然后我又撤销了刚才改的代码,再刷新请求又返回200
    • 但是其实我的内容没有改变,只是根据我修改的时间来判断,就不太准了

解决这个问题并不难,直接把下一位主角请上来

Etag

ETag是实体标签的缩写,根据实体内容生成的一个hash戳,只有内容改变了Etag才变

流程一样,还是客户端第一次访问资源时,服务端会把Etag和数据一起返回

再次访问资源时,请求头就会有个If-None-Match字段并且也会发送给服务端

一样的关键点

服务端会通过客户端发来的If-None-MatchEtag的值比较

  • 相同: 返回304状态码,使用缓存文件
  • 不相同: 返回200状态码,请求资源

强制不缓存

曾经有道题目问的是不缓存有哪些方式?

其实很简单,只要在设置Cache-Control: no-store就可以了

但是很多人也都见过no-cache这个值,实际上它依然会缓存但是每次都像服务器发请求罢了

跨域

跨域是前端同学见怪不怪的问题了,浏览器本着安全的原则采用了同源策略

要求只有域名协议端口号`都相同的才可以进行请求

概念的东西,我就不啰嗦了,下面直接开始说跨域的几种方式吧

  1. jsonp
    • 通过script的src来进行跨域请求,把数据包在一个函数内传递过来
    优点:使用简单、兼容性好
    缺点:只支持get请求,不够安全有XSS攻击的危险
  1. cors
    • 发送请求时会附带一个Origin头部包含请求页面的源信息(协议、域名、端口号)

    • 服务端根据头信息来进行处理,如果接受就在Access-Control-Allow-Origin头部回发相同的源信息实现跨域

    优点:使用方便
    缺点:浏览器兼容问题,修改主要在后端
  1. postMessage
    • 两个页面(窗口)之间的通信,可以和内嵌的iframe通信
    • iframe.contentWindow.postMessage(数据, 目标域名)
    优点:H5提供的API,使用方便
    缺点:浏览器兼容问题,而且需要依赖iframe
  1. 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上不安全
  1. domain
    • 二级页面通过document.domain设置相同的域名,强制实现了同域
    优点:设置方便
    缺点:依赖iframe,只支持一级和二级域名
  1. webSocket
    • 双工通信,没有跨域限制,需要前后端建立websocket连接,开始通信
   优点:H5的API,用法简单
   缺点:兼容问题,需要后端提供ws服务

网络安全

XSS

用户输入的内容可能会有恶意代码

所以,一句话就是转义用户输入的内容,转义转义转义(encodeURICompoent)

// 转义html里的字符
function encodeHtml(str) {
    return str.replace(/&/g, '&amp;').
        replace(/"/g, '&quot;').
        replace(/'/g, '&apos').
        replace(/</g, '&lt;').
        replace(/>/g, '&gt;')
}

CSRF

跨站请求伪造,如:钓鱼网站

  1. 验证码校验
    • express可以用个svg-captcha生成验证码,后台进行校验
  2. 判断来源 referer
    • 请求头里的referer判断来源,不一致的不处理
  3. 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,回车后发生了什么

这种问题在回答方面可大可小,可深可浅,大致流程还是亘古不变的,只不过要看是不是想深究其因了

下面我就写出来,我个人认为的过程吧

  1. DNS将URL解析为IP
    • 有缓存,直接返回缓存
    • 无缓存,继续递归解析
  2. DNS解析得到服务器的IP,与服务器建立TCP连接
    • IP协议:选择传输路线,负责找到
    • TCP协议:三次握手、分片、可靠传输、重新发送的机制
  3. 浏览器通过http协议发送请求
    • 请求行、请求头、请求体
  4. 服务器接收请求后,开始查库,读文件,拼接要返回的http响应
  5. 浏览器收到html文件开始渲染
  6. 解析html为dom树,解析css为css-tree,最终生成render-tree渲染树,阻塞渲染
  7. 遍历渲染树开始布局,计算每个节点的大小位置信息
  8. 将渲染树每个节点绘制到页面上
  9. 加载js文件,执行js脚本
  10. 回流reflow和重绘repaint

就这么10条吧,其实每一条都有可以深入展开的内容,不过我这里就不一一介绍了,毕竟我也知道的甚少,就不装腔作势了,哈哈

点到为止

对于网络方面的知识我并不熟悉,也是在学习一点点的皮毛,分享给大家也是为了和大家一起进步

好了,就写到这里吧,感谢大家的观看了,886