计网
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 Method#
get获取数据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:可接收的压缩算法gzipAccept-Language:zh-cn
Authorization:Web 认证信息Host:请求的域名是什么User-Agent:浏览器信息If-Match If-Modified-Since If-None-Match If-RangeCookie
响应首部字段#
ETag:资源的匹配信息Location:提供重定向urlServer:HTTP 服务器的安装信息Set-Cookie
实体首部字段#
包含在请求报文和响应报文中的实体部分所使用的首部,用于补充内容的更新时间等与实体相关的信息
Content-Type: text/htmlKeep-Alive: timeout=15, max=100Allow:请求资源允许使用的方法ContentContent-Encoding:返回数据的压缩算法,如gzipContent-LanguageContent-LengthContent-Type:返回 / 发送数据的格式,如application/json
Expires Last-Modified
缓存相关#
Cache-Control ExpiresLast-Modified If-Modified-SinceEtag If-None-MatchOSI 七层模型#
- 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 & HTTP#
HTTP:无状态(stateless)协议。HTTP 协议自身不对请求和响应之间的通信状态进行保存。即协议对于发送过的请求或响应都不做持久化处理
区别#
HTTP:无状态无连接,而且是明文传输,不安全 80HTTPS:传输内容加密,身份验证,保证数据完整性HTTP + SSL/TLS443 在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 请求数也是可以没有上限地持续发送