计网
状态码#
HTTP#
分类分类 | 分类描述 |
---|---|
1** | 信息响应,服务器收到请求,需要请求者继续执行操作 |
2** | 成功响应,操作被成功接收并处理 |
3** | 重定向,需要进一步的操作以完成请求 |
4** | 客户端错误,请求包含语法错误或无法完成请求 |
5** | 服务器错误,服务器在处理请求的过程中发生了错误 |
#
常见状态码- 200 - 请求成功
- 204 - 请求处理成功,但没有资源可返回
- 206 - 对资源的某一部分进行请求
- 301 - 资源被永久转移到其它 URL(永久重定向到新的 location) Moved Permanently
- 302 - 资源临时移动(临时重定向) Found
- 303 - See Other
- 304 - 所请求的资源未修改
- 307 - 临时重定向 Temporary Redirect
- 308 - Permanent Redirect
- 400 - 请求报文存在语法错误
- 403 - 没有权限
- 404 - 请求的资源不存在
- 500 - 内部服务器错误
- 502 - 网关错误
- 504 - 网关超时
关于302 303 307
- HTTP1.0 -> 302 HTTP1.1 -> 303 307
- 客户端发送POST请求收到302状态码,由于无法向新的URI发送重复请求(需要和用户确认),会把POST请求变为GET请求
- 302 允许各种各样的重定向,一般情况下都会实现为到 GET 的重定向,但是不能确保 POST 会重定向为 POST
- 303 只允许任意请求到 GET 的重定向
- 307 和 302 一样,除了不允许 POST 到 GET 的重定向
308 的定义实际上和 301 是一致的,唯一的区别在于,308 状态码不允许浏览器将原本为 POST 的请求重定向到 GET 请求上。
#
HTTP Methodget
获取数据post
新建数据patch/put
更新数据delete
删除数据
#
Get 和 Post 的区别?- 缓存:
get
请求的数据是可以缓存的;post
是不可缓存的。 - 功能
get
请求类似于查找的过程,用户获取数据,可以不用每次都与数据库连接,所以可以使用缓存。post
做的一般是修改和删除的工作,所以必须与数据库交互,所以不能使用缓存。
- 传参:
get
传参,参数是在 url 中的;post
传参,参数是在请求体中。 - 安全性:
get
不安全,post
较为安全:post
易于防止CSRF
。 - 参数长度:
get
参数长度有限,是较小的;post
传参长度不受限制。
let params = new URLSearchParams();params.append('pid', 123);?
#
get 请求传参长度的误区误区:我们经常说 get 请求参数的大小存在限制,而 post 请求的参数大小是无限制的。
HTTP
协议未规定GET
和POST
的请求长度限制GET
的最大长度显示是因为:浏览器和 web 服务器限制了 URL 的长度不同的浏览器和 WEB 服务器,限制的最大长度不一样
要支持
IE
,则最大长度为2083byte
,若只支持Chrome
,则最大长度8182byte
#
HTTP 首部HTTP
请求报文:请求方法、URI
、HTTP
版本、HTTP
首部字段HTTP
响应报文:HTTP
版本、状态码、HTTP
首部字段
HTTP
首部字段#
- 首部字段名:字段值
#
通用首部字段Cache-Control
:能够控制缓存的行为Connection
- 控制不再转发给代理的首部字段
- 管理持久连接
Connection: Keep-Alive / close
一次 TCP 连接重复使用
Date
:表明创建 HTTP 报文的日期和时间Warning
:会告知用户一些与缓存相关的问题的警告
#
请求首部字段Accept
:告知服务器,用户代理能够处理的媒体类型及媒体类型的相对优先级Accept-Charset
:优先的字符集Accept-Encoding
:可接收的压缩算法gzip
Accept-Language
:zh-cn
Authorization
:Web 认证信息Host
:请求的域名是什么User-Agent
:浏览器信息If-Match If-Modified-Since If-None-Match If-Range
Cookie
#
响应首部字段ETag
:资源的匹配信息Location
:提供重定向url
Server
:HTTP 服务器的安装信息Set-Cookie
#
实体首部字段包含在请求报文和响应报文中的实体部分所使用的首部,用于补充内容的更新时间等与实体相关的信息
Content-Type: text/html
Keep-Alive: timeout=15, max=100
Allow
:请求资源允许使用的方法Content
Content-Encoding
:返回数据的压缩算法,如gzip
Content-Language
Content-Length
Content-Type
:返回 / 发送数据的格式,如application/json
Expires Last-Modified
#
缓存相关Cache-Control ExpiresLast-Modified If-Modified-SinceEtag If-None-Match
#
OSI 七层模型- TCP 属于传输层
- 发送数据是封装过程 接收则是解封装
#
物理层通过物理手段 ( 网线,光纤,无线 ) 将设备连接在一起,实现0/1电信号 (比特流) 的透明传输
#
数据链路层通过以太网协议,对0/1电信号进行分组,让双方计算机都能够识别
将来自物理层的原始数据进行 MAC 地址的封装与解封装
点到点传输
以太网协议:规定一组电信号构成一个数据包,即 帧
MAC地址:通过MAC地址确定接收的人
广播:向同子网中全部计算机发送数据包,其它计算机根据数据包中接收者的
MAC地址
来判断是否接收数据包
#
网络层如果是同一个子网,我们就用广播的形式把数据传送给对方,如果不是同一个子网的,我们就会把数据发给网关,让网关进行转发
路由器 数据包分组
将数据链路层的数据进行 IP 地址的封装与解封装
数据链路层是解决同一网络内节点之间的通信,而网络层主要解决不同子网间的通信
IP协议判断双方是否在同一个子网
子网掩码:网络位 + 主机位 组成
ARP地址解析协议:通过广播接收者的IP地址来获取接收者的MAC地址
#
传输层传输层的功能就是建立端口到端口的通信,而相比之下网络层的功能是建立主机到主机的通信
- 定义传输数据的协议和端口 TCP UDP
- 将从下层接收的数据进行分段和传输,到达目的地址后再进行重组
- 向用户提供可靠的、透明的、端到端的数据传输,以及差错控制和流量控制机制
- TCP 流量控制
#
会话层会话层建立、管理和终止应用程序进程之间的会话和数据交换
#
表示层主要是进行对接收的数据进行解释、加密与解密、压缩与解压缩等
#
应用层将输入的域名url
变成ip
地址通信
DNS解析
终端应用
#
TCP & UDP- TCP 是面向连接的、可靠的、基于字节流的传输层通信协议
对比 | UDP | TCP |
---|---|---|
是否连接 | 无连接 | 面向连接 |
是否可靠 | 不可靠传输,不使用流量控制和拥塞控制 | 可靠传输,使用流量控制和拥塞控制 |
连接个数 | 支持一对一,一对多,多对一和多对多通信 | 只能一对一通信 |
传输方式 | 面向报文 | 面向字节流 |
首部开销 | 首部开销小,仅8字节 | 首部最小20字节,最大60字节 |
适用场景 | 适用于实时应用 ( IP电话、视频会议、直播等 ) | 适用于要求可靠传输的应用,例如文件传输 |
#
连接方面- TCP 面向连接,UDP 不需要连接
- TCP 需要三次握手四次挥手请求连接 TCP 是如何实现可靠连接的?
- 超时重传
#
可靠性- TCP 是可靠传输;一旦传输过程中丢包的话会进行重传
- UDP 是不可靠传输,但会最大努力交付
#
工作效率- UDP 实时性高,比 TCP 工作效率高
- 因为不需要建立连接,更不需要复杂的握手挥手以及复杂的算法,也没有 4 重传机制
#
是否支持多对多- TCP 是点对点的
- UDP 支持一对一,一对多,多对多
#
首部大小- TCP 首部占 20 字节
- UDP 首部占 8 字节,首部开销小。同样的报文内容,UDP 会比 TCP 更高效。
#
拥塞控制、流量控制- TCP 有拥塞控制和流量控制机制,保证数据传输的安全性。
- UDP 则没有,即使网络非常拥堵了,也不会影响 UDP 的发送速率。
#
三次握手四次挥手SYN(Synchronize) 同步
ACK 确认
ACK
:该位为1
时,「确认应答」的字段变为有效,TCP 规定除了最初建立连接时的SYN
包之外该位必须设置为1
。FIN
:该位为1
时,表示今后不会再有数据发送,希望断开连接。当通信结束希望断开连接时,通信双方的主机之间就可以相互交换FIN
位置为 1 的 TCP 段。
#
三次握手实质:客户端连接服务器指定端口 建立 TCP 连接,并同步双方的序列号和确认号,交换TCP窗口大小
信息
- 服务端调用
listen
系统命令,进入监听状态,等待客户端的连接。 - 客户端向服务端发送
连接请求报文
。客户端会随机初始化「序号」x
,并将中SYN
标志位置为1
,发送SYN
报文。SYN=1 seq=x
- 服务端收到请求报文,向 客户端 发送
连接确认报文
。服务端也随机初始化自己的「序号」y
,其次将TCP首部的「确认应答号」字段填入x+1
,接着把SYN
和ACK
标志位置为1
。SYN=1 ACk=1 seq=y ack=x+1
- 客户端 收到 服务端的连接确认报文后,还要向 服务端
发出确认
,「确认应答号」为y+1
,「序号」为x+1
。ACK=1 seq=x+1 ack=y+1
- 服务端 收到 客户端 的确认后,
连接建立
第三次握手是可以携带数据的,前两次握手是不可以携带数据的
为什么三次
三次握手才可以阻止历史重复连接的初始化(主要原因)
三次握手才可以同步双方的初始序列号
三次握手才可以避免资源浪费 (SYN泛洪?
第一次握手:客户端发送网络包,服务端收到了。 服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。
第二次握手:服务端发包,客户端收到了。 客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。
第三次握手:客户端发包,服务端收到了。 服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。
因此,需要三次握手才能确认双方的接收与发送能力是否正常
#
四次挥手- 当主动方关闭连接时,会发送
FIN
报文,此时主动方的连接状态由ESTABLISHED
变为FIN_WAIT1
。当被动方收到FIN
报文后,内核自动回复ACK
报文,连接状态由ESTABLISHED
变为CLOSE_WAIT
,顾名思义,它在等待进程调用close
函数关闭连接。当主动方接收到这个ACK
报文后,连接状态由FIN_WAIT1
变为FIN_WAIT2
,主动方的发送通道就关闭了。 - 再来看被动方的发送通道是如何关闭的。当被动方进入
CLOSE_WAIT
状态时,进程的read
函数会返回 0,这样开发人员就会有针对性地调用close 函数
,进而触发内核发送FIN
报文,此时被动方连接的状态变为LAST_ACK
。当主动方收到这个FIN
报文时,内核会自动回复ACK
,同时连接的状态由FIN_WAIT2
变为TIME_WAIT
,Linux
系统下大约1 分钟
后 TIME_WAIT 状态的连接才会彻底关闭。而被动方收到ACK
报文后,连接就会关闭。
- 客户端打算关闭连接,此时会发送一个 TCP 首部
FIN
标志位被置为1
的报文,也即FIN
报文,之后客户端进入FIN_WAIT_1
状态。 - 服务端收到该报文后,就向客户端发送
ACK
应答报文,接着服务端进入CLOSED_WAIT
状态。 - 客户端收到服务端的
ACK
应答报文后,之后进入FIN_WAIT_2
状态。 - 等待服务端处理完数据后,也向客户端发送
FIN
报文,之后服务端进入LAST_ACK
状态。 - 客户端收到服务端的
FIN
报文后,回一个ACK
应答报文,之后进入TIME_WAIT
状态 - 服务器收到了
ACK
应答报文后,就进入了CLOSE
状态,至此服务端已经完成连接的关闭。 - 客户端在经过
2MSL
一段时间后,自动进入CLOSE
状态,至此客户端也完成连接的关闭。
MSL
是 Maximum Segment Lifetime,报文最大生存时间
为什么需要三次握手,四次挥手呢?
- 3次握手的作用就是双方都能明确自己和对方的收、发能力是正常的,三次连接是保证可靠性的最小握手次数。
- 4次挥手呐,TCP的全双工通信断开连接,需要双方的都确认断开。当客户端确认自己没有数据要传给服务器时,并不能保证服务器也没有数据要发送了。前两次挥手是客户端和服务器对连接断开的确认,第三次服务器会将剩下的数据发给客户端。
#
TCP拓展- 粘包
- TCP可靠传输:超时重传
- TCP滑动窗口:控制字节流存放大小?
- TCP流量控制:控制发送方发送速率,保证接收方来得及
- TCP拥塞控制:网络拥塞时,控制重传速率
Ref
#
DNS解析#
域名解析www.qq.com.. -> .com -> qq.com -> www.qq.com跟域名 -> 顶级域名 -> 二级域名 -> 三级域名
#
多级缓存- 缓存命中:浏览器缓存 => 操作系统缓存 =>
LDNS
本地区域名服务器缓存(学校机房 /ISP
) LDNS
=> 根域名服务器 根域名服务器返回给LDNS
一个所查询的主域名服务器gTLD
地址LDNS
=>gTLD
发起请求 返回域名对应的Name Server
域名服务器地址LDNS
=>Name Server
查询请求域名的对应IP地址 返回对应IP以及TTLLDNS
根据返回的TTL对IP进行缓存 并将结果返回给用户TTL: time to live
域名缓存的最长时间
#
解析优化原因:DNS解析的过程中浏览器什么都不会做直到DNS查询完毕
使用TTL:TTL: time to live
域名缓存的最长时间
负载均衡:在DNS服务器中为同一个主机名配置多个IP地址,在应答DNS查询时,DNS服务器对每个查询将以DNS文件中主机记录的IP地址按顺序返回不同的解析结果,将客户端的访问引导到不同的机器上去,使得不同的客户端访问不同的服务器,从而达到负载均衡的目的,可以根据每台机器的负载量或该机器离用户地理位置的距离入手
#
HTTPS & HTTPHTTP:无状态(stateless)
协议。HTTP 协议自身不对请求和响应之间的通信状态进行保存。即协议对于发送过的请求或响应都不做持久化处理
#
区别HTTP
:无状态无连接,而且是明文传输,不安全 80HTTPS
:传输内容加密,身份验证,保证数据完整性HTTP + SSL/TLS
443 在HTTP 与 TCP层之间加入了SSL/TLS
协议
#
HTTP 的不足- 通信使用明文,内容可能会被窃听 -> 通信加密
数据加密 - 不验证通信方的身份,因此有可能遭遇伪装 ->
SSL HTTPS
数字证书 - 无法证明报文的完整性,所以有可能已遭篡改 -> 中间人攻击 MD5 数字签名
#
数字证书- 解决通信身份可能被伪装问题
- 服务器运营人员向第三方证书机构提交 CA 公钥、组织信息、域名等信息进行申请认证
- 数字证书机构通过线上线下等手段去验证所提供的信息是否合法。合法的话会向申请者颁发证书(包含 CA 公钥、证书机构和所有者组织信息、证书有效时间、序列号等信息,还包含一个签名(使用散列函数计算公开明文的消息摘要并通过 CA 的私钥进行加密 => 签名
- 客户端向目标服务器发起请求时会返回相应的证书文件
- 客户端读取证书中信息,进行相同的散列函数计算得到消息摘要。通过 CA 中的公钥解密签名数据,对比证书的消息摘要是否一致来判断是否合法
#
完整性检测 - 数字签名- 将一段文本通过
hash
函数生成消息摘要,再通过客户端的私钥进行加密生成数字签名 - 服务器收到数字签名后先用公钥进行解密 得到消息摘要
- 然后对收到的原文也进行
hash
生成消息摘要 - 比较前后两次消息摘要 如果相同 则证明完整没有被篡改
- 然后对收到的原文也进行
#
HTTPS 实现原理HTTP + 加密 + 认证 + 完整性保护 = HTTPS
过程
- 客户端发送消息给服务器(包含可用的加密算法和压缩算法
- 服务器返回消息给客户端(包含选用的加密和压缩算法以及数字证书认证机构 CA 签发的证书(包含公钥 + 证书所应用的域名范围
- 客户端去验证公钥证书 是否合法
- 客户端使用伪随机数生成传输信息所用的对称密钥,然后通过证书的公钥去传输对称密钥
- 服务端接收到信息后,用自己的私钥去解密来获得对称密钥
- 服务端使用对称密钥与客户端进行通信(此时双方都已经拥有了对称密钥
SSL 公钥加密的算法
- 对称加密的问题:密钥分发的问题 安全性问题
HTTPS 采用 共享密钥(对称加密) 和 公开密钥(非对称加密)两者混用的加密机制
- 非对称:交换对称密钥。通信建立前
- 对称:信息交换。通信过程中
#
HTTP 版本- HTTP/0.9:只能进行
get
请求,发送纯文本 - HTTP/1.0:添加了
POST、HEAD、OPTION、PUT、DELETE
等 - HTTP/1.1:
- 默认支持了长连接
keep-alive
:旨在建立 1 次 TCP 连接后进行多次请求和响应的交互Keep-Alive: timeout=5, max=100
- 管线化:不用等待响应亦可直接发送下一个请求,就能够做到同时并行发送多个请求
- 虽然是无状态协议,但为了实现期望的保持状态功能,于是引入了
Cookie
技术(通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态 - 增加了
host
域,而且节约带宽?
- 默认支持了长连接
- HTTP/2:
- 多路复用:让所有的通信都在一个 TCP 连接上完成,实现了请求的并发
- 头部压缩:利用 HPACK 算法压缩头部的
User-Agent Cookie Accept Server Rabge
等字段 - 服务器推送:使得服务器可以预测客户端需要的资源,主动推送到客户端
关于HTTP的队头阻塞问题
HTTP/1.0
每次请求都会建立一个TCP连接 请求结束后立即断开连接HTTP/1.1
每一个连接都是长连接。对于同一个TCP连接可以发送多个HTTP/1.1
请求。- 不必等前一个返回就可以发送下一个 --> 解决了
HTTP/1.0
中客户端的队头阻塞 -->Pipline
- 但是
HTTP/1.1
要求服务端返回响应 按照请求发送顺序返回 -->1.0
的服务端的队头阻塞
- 不必等前一个返回就可以发送下一个 --> 解决了
HTTP/2.0
- 二进制封帧
- 在
HTTP/1.1
数据包是文本格式的, 而HTTP/2
的数据包是二进制格式 - 采用帧的传输方式可以将请求和响应的数据分割的更小
- 在
- 多路复用
- HTTP/1.1 并发多个请求需要多个TCP链接,且单个域名有6-8个TCP链接请求限制
- 同一域名下所有通信在单个TCP链接下完成,且这个链接可以并行请求和响应 互不干扰
- 二进制封帧
使用长连接之后,客户端、服务端怎么知道本次传输结束呢?
- 判断传输数据是否达到了
Content-Length
指示的大小 - 动态生成的文件没有
Content-Length
,它是分块传输chunked
,这时候就要根据chunked
编码来判断,chunked
编码的数据在最后有一个空chunked
块,表明本次传输数据结束
#
一个 tcp 连接能发几个 http 请求?如果是 HTTP 1.0 版本协议,一般情况下,不支持长连接,因此在每次请求发送完毕之后,TCP 连接即会断开,因此一个 TCP 发送一个 HTTP 请求,但是有一种情况可以将一条 TCP 连接保持在活跃状态,那就是通过 Connection 和 Keep-Alive 首部,在请求头带上 Connection: Keep-Alive,并且可以通过 Keep-Alive 通用首部中指定的,用逗号分隔的选项调节 keep-alive 的行为,如果客户端和服务端都支持,那么其实也可以发送多条,不过此方式也有限制,可以关注《HTTP 权威指南》4.5.5 节对于 Keep-Alive 连接的限制和规则。
而如果是 HTTP 1.1 版本协议,支持了长连接,因此只要 TCP 连接不断开,便可以一直发送 HTTP 请求,持续不断,没有上限; 同样,如果是 HTTP 2.0 版本协议,支持多用复用,一个 TCP 连接是可以并发多个 HTTP 请求的,同样也是支持长连接,因此只要不断开 TCP 的连接,HTTP 请求数也是可以没有上限地持续发送