下面是我最近整理的一份计算机网络相关的知识。大家可以收藏+点赞哈。
001.计算机网络结构
分层的意义在于简化问题,各层之间独立则让复杂的问题简单化,当其中一层的技术变化时,只要层间接口关系保持不变,其他层不受影响
下面给出 OSI 理想的七层协议:
002.数据传输过程
包、帧、数据包、段、消息 以上五个术语都用来表述数据的单位,大致区分如下:
- 包可以说是全能性术语
- 帧用于表示数据链路层中包的单位
- 数据包是 IP 和 UDP 等网络层以上的分层中包的单位
- 段则表示 TCP 数据流中的信息
- 消息是指应用协议中数据的单位
下图以用户 a 向用户 b 发送邮件为例子:
003.TCP 与 UDP
该两者都是传输层的协议
UDP
用户数据包协议,是一个简单的面向数据报的通信协议,即对应用层交下来的报文,不合并,不拆分,只是在其上面加上首部后就交给了下面的网络层
无论应用层交给UDP多长的报文,它统统发送,一次发送一个报文而对接收方,接到后直接去除首部,交给上面的应用层就完成任务
TCP
传输控制协议,是一种可靠、面向字节流的通信协议,把上面应用层交下来的数据看成无结构的字节流来发送
可以想象成流水形式的,发送方TCP会将数据放入“蓄水池”(缓存区),等到可以发送的时候就发送,不能发送就等着,TCP会根据当前网络的拥塞状态来确定每个报文段的大小
004. TCP
TCP 头如下图所示,其包含了三次握手中需要的标志位(SYN、ACK)和两个值(序号和确认号)
005. TCP 可靠性
什么叫可靠性?就是 TCP 在传输数据的过程,无差错、不丢失、不重复、并且按序到达
实现 TCP 可靠性靠的特性是:
- 序列号和确认应答信号
- 超时重发控制
- 连接管理
- 滑动窗口控制
- 流量控制
- 拥塞控制
详情可见TCP协议可靠性是如何保证 之 滑动窗口,超时重发,序列号确认应答信号 (qq.com)
006.三次握手、四次挥手
三次握手
主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备
过程如下:
- 第一次握手:客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 ISN(c),此时客户端处于 SYN_SENT 状态
- 第二次握手:服务器收到客户端的 SYN 报文之后,会以自己的 SYN 报文作为应答,为了确认客户端的 SYN,将客户端的 ISN+1作为ACK的值,此时服务器处于 SYN_RCVD 的状态
- 第三次握手:客户端收到 SYN 报文之后,会发送一个 ACK 报文,值为服务器的ISN+1。此时客户端处于 ESTABLISHED 状态。服务器收到 ACK 报文之后,也处于 ESTABLISHED 状态,此时,双方已建立起了连接
上述每一次握手的作用如下:
- 第一次握手:客户端发送网络包,服务端收到了 这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。
- 第二次握手:服务端发包,客户端收到了 这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常
- 第三次握手:客户端发包,服务端收到了。 这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常
通过三次握手,就能确定双方的接收和发送能力是正常的。之后就可以正常通信了
为什么不是两次握手?
如果是两次握手,发送端可以确定自己发送的信息能对方能收到,也能确定对方发的包自己能收到,但接收端只能确定对方发的包自己能收到 无法确定自己发的包对方能收到
并且两次握手的话, 客户端有可能因为网络阻塞等原因会发送多个请求报文,延时到达的请求又会与服务器建立连接,浪费掉许多服务器的资源
丢包情况
如果客户端的 ACK 未送达服务器
Server端:由于Server没有收到ACK确认,因此会每隔 3秒 重发之前的SYN+ACK(默认重发五次,之后自动关闭连接进入CLOSED状态),Client收到后会重新传ACK给Server
Client端,会出现两种情况:
- 在Server进行超时重发的过程中,如果Client向服务器发送数据,数据头部的ACK是为1的,所以服务器收到数据之后会读取 ACK number,进入 establish 状态
- 在Server进入CLOSED状态之后,如果Client向服务器发送数据,服务器会以RST包应答
四次挥手
tcp终止一个连接,需要经过四次挥手
过程如下:
- 第一次挥手:客户端发送一个 FIN 报文,报文中会指定一个序列号。此时客户端处于 FIN_WAIT1 状态,停止发送数据,等待服务端的确认
- 第二次挥手:服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序列号值 +1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT状态
- 第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 FIN 报文,且指定一个序列号。此时服务端处于
LAST_ACK的状态 - 第四次挥手:客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值 +1 作为自己 ACK 报文的序列号值,此时客户端处于 TIME_WAIT状态。需要过一阵子以确保服务端收到自己的 ACK 报文之后才会进入 CLOSED 状态,服务端收到 ACK 报文之后,就处于关闭连接了,处于 CLOSED 状态
原因
服务端在收到客户端断开连接Fin报文后,并不会立即关闭连接,而是先发送一个ACK包先告诉客户端收到关闭连接的请求,只有当服务器的所有报文发送完毕之后,才发送FIN报文断开连接,因此需要四次挥手
007.HTTP
概念
HTTP 是一种超文本运输协议,其目的是为了实现网络之间的通信
传输的数据并不是计算机底层中的二进制包,而是完整的、有意义的数据,如HTML 文件, 图片文件, 查询结果等超文本,能够被上层应用识别
样子
HTTP 的消息结构分成了 头部信息 + 主题信息,具体则分成了:
- 起始行:描述请求或响应的基本信息
- 头部:使用 key-value 形式更详细地说明报文
- 空行
- 实体:实际传输的数据,它不一定是纯文本,可以是图片、视频等二进制数据
HTTP 的由于是客户/服务器模式,分成了请求与响应:
请求报文格式的头部长这样:
GET /home HTTP/1.1
具体为请求方法 + 空格 + 路径 + 空格 + HTTP版本号
响应报文请求行则对应如下:
HTTP/1.1 200 ok
具体为 HTTP版本号 + 状态码 + 原因
特性:
- 支持客户/服务器模式
- 简单快速易扩展:客户向服务器请求服务时,只需传送请求方法和路径。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快
- 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记
- 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间
- 无状态:HTTP协议无法根据之前的状态进行本次的请求处理
- 明文:协议里的报文(准确地说是 header 部分)不使用二进制数据,而是用简单可阅读的文本形式
008.请求头/响应头
概念
HTTP头字段,是指在超文本传输协议(HTTP)的请求和响应消息中的消息头部分
有哪些
HTTP 协议规定了非常多的头部字段,实现各种各样的功能,但基本上可以分为四大类:
- 通用字段:在请求头和响应头里都可以出现
- 请求字段:仅能出现在请求头里,进一步说明请求信息或者额外的附加条件
- 响应字段:仅能出现在响应头里,补充说明响应报文的信息
- 实体字段:它实际上属于通用字段,但专门描述 body 的额外信息
009.状态码
有哪些
HTTP 的状态码为三位数,被分为五类:
- 1xx: 表示目前是协议处理的中间状态,还需要后续操作。
- 2xx: 表示成功状态。
- 3xx: 重定向状态,资源位置发生变动,需要重新请求。
- 4xx: 请求报文有误。
- 5xx: 服务器端发生错误
具体可以参考之前写的面试官:说说HTTP 常见的状态码有哪些,适用场景?
010.URL 与 URI
概念
- URI 统一资源标识符,是用于标识某一互联网资源名称的字符串
- URL 统一资源定位符,标志了资源的位置,如同在网络上的门牌
一个是资源的标志,一个是资源的查找路径
样子
标准格式如下:
以https://juejin.im:80/search?query=vue&type=all为例,其中:
https,是协议juejin.im,是服务器443,是端口号/search,是路径?query=vue&type=all,是询问
011.请求方法
概念
想要获取网络资源,就需要客户端发生一个指令,这个指令就是请求方法
有哪些
- GET:获取资源,可以理解为读取或者下载数据
- HEAD:获取资源的元信息
- POST:向资源提交数据,相当于写入或上传数据
- PUT:类似 POST
- DELETE:删除资源
- CONNECT:建立特殊的连接隧道
- OPTIONS:列出可对资源实行的方法,跨域的时候浏览器会自动发送
- TRACE:追踪请求 - 响应的传输路径
区别
以 get 请求与 post为例,两者的区别:
- GET在浏览器回退时是无害的,而POST会再次提交请求。
- GET产生的URL地址可以被Bookmark,而POST不可以。
- GET请求会被浏览器主动cache,而POST不会,除非手动设置。
- GET请求只能进行url编码,而POST支持多种编码方式。
- GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
- GET请求在URL中传送的参数是有长度限制的,而POST没有。
- 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
- GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
- GET参数通过URL传递,POST放在Request body中
具体可见之前写的文章面试官:说一下 GET 和 POST 的区别?
012.请求资源
前面讲到,HTTP 传输的内容是有意义的数据,如图片、HTML、音频等,由响应头Content-type,常见的数据类型有:
- text:即文本格式的可读数据,如 text/html 了,表示超文本文档,此外还有纯文本 text/plain、样式表 text/css
- image:即图像文件,有 image/gif、image/jpeg、image/png 等
- audio/video:音频和视频数据,例如 audio/mpeg、video/mp4 等
- application:数据格式不固定,可能是文本也可能是二进制,必须由上层应用程序来解释。常见的有application/json,application/javascript、application/pdf
资源压缩
通过会投通过响应头设置 encoding-Encoding 决定,告诉数据是用的什么编码格式,这样对方才能正确解压缩,还原出原始
的数据:
- gzip:GNU zip 压缩格式,也是互联网上最流行的压缩格式
- deflate:zlib(deflate)压缩格式,流行程度仅次于gzip
- br:一种专门为 HTTP 优化的新压缩算法(Brotli)
013.大文件上传
压缩
一种方案是对资源文件进行压缩,请求头设置 Accept-encoding告诉服务端浏览器支持的压缩格式,服务端通过设置相应头encoding-Encoding告诉资源文件通过哪种形式压缩过文件
分块上传
在响应报文里用头字段 Transfer-Encoding: chunked 来表示,意思是报文里的 body 部分不是一次性发过来的,而是分成了许多的块(chunk)逐个发送
注意:Transfer-Encoding: chunked 与 Transfer-Encoding: chunked 两个字段是互斥的,也就是响应头报文中这两个字段不可能同时出现
范围请求
允许客户端在请求头里使用专用字段来表示只获取文件的一部分
服务器不是必有范围请求这个功能,因此如果有这个功能则通过响应头 AcceptRanges: bytes 明确告知客户端:“我是支持范围请求的”
若服务端支持范围请求,则:
-
请求头通过 Range 决定,格式是“bytes=x-y”,其中的 x 和 y 是以字节为单位的数据范围
- 要注意 x、y 表示的是“偏移量”,范围必须从 0 计数,例如前 10 个字节表示为“0-9”,第二个 10 字节表示为“10-19”,而“0-10”实际上是前 11 个字节
-
响应头添加一个响应头字段Content-Range,告诉片段的实际偏移量和资源的总大小,格式是bytes x-y/length
014.HTTP连接
短连接
HTTP 0.9 版本采用短连接的形式,简单的请求-应答形式
长连接
将多个短连接合并到一个长连接中,在 HTTP1.1 中,这是默认的连接方式
客户端: 请求头中是通过Connection: keepalive来表示
服务端: 如果服务器支持长连接,它总会在响应报文里放一个Connection: keep-alive字段
当需要关闭长连接的时候,客户端只需要传递Connection: close即可
并发连接
对一个域名发起多个长连接,用数量来解决质量的问题,目前浏览器大概最大支持6个并发量
如果觉得并发数量不都,还可通过设置多个域名,这些域名都指向同一个服务器
015.Cookie
目的
解决 HTTP 无状态问题
头部信息
通过响应头set-cookie与请求头cookie决定
浏览器收到响应报文,看到里面有 Set-Cookie,知道这是服务器给的身份标识,于是就保存起来,下次再请求的时候就自动把这个值放进 Cookie 字段里发给服务器。
属性
过期相关
- expires:cokire的有效时间,用的是绝对时间点
- Max-Age:用的是相对时间,单位是秒,浏览器用收到报文的时间点再加上 Max-Age,就可以得到失效的绝对时间
Expires 和 Max-Age 可以同时出现,两者的失效时间可以一致,也可以不一致,但浏览器会优先采用 Max-Age 计算失效期
路径相关
- domain:制定的域名可做到与结尾匹配一致
- path:限定制定cookire的发送范围的文件的目录
域名相关
浏览器在发送 Cookie 前会从 URI 中提取出 host 和 path 部分,对比 Cookie 的属性。如果不满足条件,就不会在请求头里发送 Cookie
-
secure:限制Web页面仅当HTTPS安全连接时,才可以发送cookie
-
HttpOnly:使JavaScript 脚本无法获得cookie,目的是防止xss对cookie 信息的窃取
-
SameSite:防止 csrf
- 值为 Strict 可以严格限定 Cookie 不能随着跳转链接跨站发送
- 值为 Lax 则略宽松一点,允许 GET/HEAD 等安全方法,但禁止 POST 跨站发
016. 缓存
主要分成了强缓存和协商缓存
协商缓存:利用的是【Last-Modified,If-Modified-Since】和 【ETag、If-None-Match】这两对请求头响应头来管理的
强制缓存:不需要发送请求到服务端,根据请求头 【expires】和【cache-control】判断是否命中强缓存
最先判断的是资源是否设置了 cache-control,例如值 maxage=30 就是资源的有效时间,相当于告诉浏览器,这个页面只能缓存 30 秒,之后就算是过期,不能用
流程图如下所示:
017.HTTP代理
概念
代理最基本的一个功能是负载均衡,控制哪台服务器资源响应请求
字段
代理服务器需要用字段 Via 标明代理的身份
018.HTTP2.0
HTTP 2.0 新特性包含:
- 二进制传输
- Header 压缩
- 多路复用
- 服务器推送
二进制传输
采用二进制格式传输数据,而非HTTP/1.x 里纯文本形式的报文 ,二进制协议解析起来更高效
HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码
Header 压缩
在客户端和服务器两端建立“字典”,用索引号表示重复的字符串,还采用哈夫曼编码来压缩整数和字符串,可以达到50%~90%的高压缩率
具体来说:
- 在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送;
- 首部表在HTTP/2的连接存续期内始终存在,由客户端和服务器共同渐进地更新;
- 每个新的首部键-值对要么被追加到当前表的末尾,要么替换表中之前的值
例如下图中的两个请求, 请求一发送了所有的头部字段,第二个请求则只需要发送差异数据,这样可以减少冗余数据,降低开销
多路复用
在 HTTP/2 中引入了多路复用的技术。多路复用很好的解决了浏览器限制同一个域名下的请求数量的问题,同时也接更容易实现全速传输,毕竟新开一个 TCP 连接都需要慢慢提升传输速度
服务器推送
改变了传统的“请求-应答”工作模式,服务器不再是完全被动地响应请求,也可以新建“流”主动向客户端发送消息。比如,在浏览器刚请求HTML的时候就提前把可能会用到的JS、CSS文件发给客户端,减少等待的延迟
详情可见:解读 HTTP1/HTTP2/HTTP3
019. HTTPS
先讲讲 HTTP 的缺点:
- 通信使用明文,传输内容可能被窃听
- 不验证后通信方的身份,容易伪装进行请求
- 无法保证报文的完整性,可能遭遇篡改
目的
解决 HTTP 传输过程不安全的问题
概念
证这些隐私数据能加密传输,让HTTP运行安全的SSL/TLS协议上,即 HTTPS = HTTP + SSL/TLS,通过 SSL证书来验证服务器的身份,并为浏览器和服务器之间的通信进行加密
020.加密算法
对称加密:使用同一个密钥对明文进行加密解密
非对称加密:一个公钥,一个私钥,使用公钥对明文进行加密,使用私钥对密文解密
混合加密:使用非对称加密的公钥加密对称加密的密钥,通过非对称加密的私钥得到对称加密的密钥。后续的交流都建立在对对称密钥的加密解密中
摘要算法:保证数据完整性,具有雪崩特性,把任意长度的数据“压缩”成固定长度、而且独一无二的“摘要”字符串
数字签名:使用私钥加密摘要,公钥解密,只要你和网站互相交换公钥,就可以用“签名”和“验签”来确认消息的真实性,因为私钥保密,黑客不能伪造签名,就能够保证通信双方的身份
数字证书与CA:CA证书认证机构,由它来给各个公钥签名,用自身的信誉来保证公钥无法伪造,是可信的。将要包含序列号、用途、颁发者、有效时间等等,把这些打成一个包再签名,完整地证明公钥关联的各种信息,形成“数字证书
021.安全性保证
在信息安全性问题中,我们常常要做到三点才能保证信息的安全:
- 信息的保密性
- 信息的完整性
- 身份识别
保密性
完整性
将信息通过摘要算法生成摘要,客户端通过公钥进行加密摘要,服务端使用私钥进行解密获得原始内容和摘要值这时服务端使用相同的hash算法对原始内容进行hash,然后与摘要值比对,如果一致,说明信息是完整的
身份识别
把发送端的公钥发送给接收端,发送端通过把自己的内容使用私钥加密然后发送给接收端,接收端只能用发送端的公钥解密,自然就验证了发送端的身份
在传输的过程中,客户端如何获得服务器端的公钥呢?
当时是服务器分发给客户端,这种情况是不安全的
如果一开始服务端发送的公钥到客户端的过程中有可能被第三方劫持,然后第三方自己伪造一对密钥,将公钥发送给客户端,当服务器发送数据给客户端的时候,中间人将信息进行劫持,用一开始劫持的公钥进行解密后,然后使用自己的私钥将数据加密发送给客户端,而客户端收到后使用公钥解密,反过来亦是如此,整个过程中间人是透明的,但信息泄露却不得而知
为了防止这种情况,出现了 CA证书认证机构,CA机构通过服务端提供的相关信息生成证书,证书内容包含了持有人的相关信息,服务器的公钥,签署者签名信息(数字签名)等,最重要的是公钥在数字证书中
当客户端发起请求时,服务器将该数字证书发送给客户端,客户端通过CA机构提供的公钥对加密密文进行解密获得散列值(数字签名),同时将证书内容使用相同的散列算法进行Hash得到另一个散列值,比对两个散列值,如果两者相等则说明证书没问题
021.Websocket
web浏览器与web服务器之间的全双工通信标准,一旦服务器和客户端简历websocket通信,之后所有的通信都依赖这个专用协议进行,通信过程中可以发送JSON、HTML、XML或图片任务格式的数据
特点:
- 支持服务器想客户端推送数据的,不必等待客户端的请求
- 减少通信量
- 请求头中会通过Upgrade首部字段告知服务器通信协议发生了变化
- 响应头,会返回状态码101 Switching Protocols 的响应
\