http协议
# HTTP 特点
超文本传输协议的缩写,是用于从服务器端传输超文本到本地浏览器的传输协议。
- 无状态,每次请求都是独立,无关的,默认不需要保留状态信息
- 基于请求/响应模型的协议
- 简单快速
- 可靠传输
# HTTP 缺点:
无状态 当请求仅仅为了获取一些数据,不需要保持连接上下文信息时,无状态可以减少开销。
但是在长连接场景中,需要保存大量的上下文信息,以免传输大量重复的信息,那么这时候无状态就是 http 的缺点了。
明文传输
协议里的报文不使用二进制,而是文本形式,报文信息暴露给外界,容易被攻击。
其中 wifi陷阱
就是利用此特点,诱导用户连接热点,通过抓取你的流量,从而窃取用户敏感信息。
队头阻塞问题 当 http 开启长连接时,共用一个 TCP ,同一时刻只能处理一个请求。当请求耗时过长,会导致其他请求处于阻塞状态。
并发连接解决,目前浏览器对于一个域名允许分配多个长连接,如Chrome 中是 6 个
# http1.0 1.1 2.0的区别
- 长链接:HTTP1.0需要使用keep-alive来建立长连接,HTTP1.1默认支持长连接
- 缓存处理:HTTP1.1多了Entity tag,If-Unmodified-Since, If-Match, If-None-Match等缓存信息(HTTP1.0 If-Modified-Since,Expires)
- 节约宽带:(设置虚拟站点,也就是说,web server上的多个虚拟站点可以共享同一个ip端口):HTTP1.0没有host域
HTTP2的优化
- HTTP2支持二进制传送(实现方便且健壮),HTTP1.x是字符串传送
- HTTP2支持多路复用:一个连接可以并发处理多个请求
- HTTP2采用HPACK压缩算法压缩头部,减小了传输体积
- HTTP2支持服务端推送
# HTTP和HTTPS有何区别
- HTTPS使用443端口,而HTTP使用80
- HTTPS需要申请证书
- HTTP是超文本传输协议,是明文传输;HTTPS是经过SSL加密的协议,传输更安全
- HTTPS比HTTP慢,因为HTTPS除了TCP握手的三个包,还要加上SSL握手的九个包
# HTTP 的请求方法
在 http/1.1 规定了以下请求方法
- GET:获取资源
- HEAD:获取资源元信息
- POST:提交数据
- PUT:修改数据
- DELETE:删除资源
- CONNECT:建立连接隧道,用于代理服务器
- OPTIONS:列出可对资源实行的请求方法,用来跨域请求
- TRACE:追踪请求-响应的传输路径
# GET 和 POST 区别
- GET :有缓存,请求长度受限,参数放在 URL 中,不安全,幂等(幂等表示执行相同的操作,结果也是相同的)
- POST:更多的编码类型,安全
- 从 TCP 角度,GET 会把请求报文一次性发出,而 POST 会分为两个 TCP 数据包,先发 header 部分,服务器响应100,再发 body 部分。(火狐浏览器除外,它的 POST 请求只发一个 TCP 包)
- 其实HTTP协议并没有要求GET/POST请求参数必须放在URL上或请求体里,也没有规定GET请求的长度,目前对URL的长度限制,是各家浏览器设置的限制。GET和POST的根本区别在于:GET请求是幂等性的,而POST请求不是
1. 幂等性,指的是对某一资源进行一次或多次请求都具有相同的副作用。例如搜索就是一个幂等的操作,而删除、新增则不是一个幂等操作。
2. 由于GET请求是幂等的,在网络不好的环境中,GET请求可能会重复尝试,造成重复操作数据的风险,因此,GET请求用于无副作用的操作(如搜索),新增/删除等操作适合用POST
2
3
4
5
6
7
# HTTP 常见状态码
大致区分 :
- 1**-信息提示
- 2**-请求成功
- 3**请求重定向
- 4**请求错误
- 5**服务器错误
几个常见的状态码,我们需要牢记
- 200-请求成功,服务器已成功处理了请求
- 301-永久重定向;
- 302-临时转移
- 304-读取缓存(协商缓存时,表示浏览器端有缓存,并且服务端未更新,不再向服务端请求资源])
- 400-请求错误,服务器不理解请求的语法
- 403-服务器拒绝请求
- 404-找不到
- 500-服务器内部错误,甩锅后端
# HTTP 缓存
强缓存和协商缓存
浏览器是根据响应头的相关字段来决定缓存的方案的。所以,后端的关键就在于,根据不同的请求返回对应的缓存字段。
web 资源的缓存策略一般由服务器来指定,可以分为两种,分别是强缓存策略和协商缓存策略。
协商缓存:当使用协商缓存策略时,会先向服务器发送一个请求,如果资源没有发生修改,则返回一个 304 状态,让浏览器使用本地的缓存副本。 如果资源发生了修改,则返回修改后的资源。协商缓存也可以通过两种方式来设置,分别是 http 头信息中的 Etag 和 Last-Modified 属性。
强缓存策略:使用强缓存策略时,如果缓存资源有效,则直接使用缓存资源,不必向服务器发送请求。强缓存策略可以通过两种方式来设置,分别为 http 头部信息中的 Expires 和 Cache-Control。
Expires 即过期时间,存在于服务端返回的响应头中,它是 http1.0 中的方式。
因为它的一些缺点(服务器的时间和浏览器的时间可能并不一致),在 http 1.1 中提出了一个新的头部属性就是 Cache-Control 属性。它提供了对资源的缓存的更精确的控制。它有很多不同的值,常用的比如我们可以通过设置 max-age 来指定资源能够被缓存的时间的大小,这是一个相对的时间,它会根据这个时间的大小和资源第一次请求时的时间来计算出资源过期的时间,因此相对于 Expires来说,这种方式更加有效一些。常用的还有比如 private ,用来规定资源只能被客户端缓存,不能够代理服务器所缓存。还有如 no-store ,用来指定资源不能够被缓存,no-cache 代表该资源能够被缓存,但是立即失效,每次都需要向服务器发起请求。
通常来说设置一种就行了,两种方式一起使用时,Cache-Control 的优先级要高于 Expires 。
区别:强缓存策略和协商缓存策略在缓存命中时都会直接使用本地的缓存副本,区别只在于协商缓存会向服务器发送一次请求。它们缓存不命中时,都会向服务器发送请求来获取资源。在实际的缓存机制中,强缓存策略和协商缓存策略是一起合作使用的。浏览器首先会根据请求的信息判断,强缓存是否命中,如果命中则直接使用资源。如果不命中则根据头信息向服务器发起请求,使用协商缓存,如果协商缓存命中的话,则服务器不返回资源,浏览器直接使用本地资源的副本,如果协商缓存不命中,则浏览器返回最新的资源给浏览器。
先通过
Cache-Control
验证强缓存是否可用如果强缓存可用,那么直接用
否则进入协商缓存,即发送 HTTP 请求,服务器通过请求头中的
If-Modified-Since
或者If-None-Match
这些条件请求字段检查资源是否更新,如果缓存有效会返回 304,如果有更新则返回200具体过程:
强缓存:
cache-control : max-age: 10000 //缓存时间
from memory cache // 内存
from disk cache // 硬盘
协商缓存
Last-modified // 当前服务器时间
ETag // 当前服务器的哈希
判断过程:先判断当前强缓存时间是否过期,没有过去就去请求本地的内存和硬盘,过期就去协商缓存,
返回if-Modified-Since(Last-modified) 和 if-no-Match(ETag)来判断当前文件是否有更新,
如果没有更新返回304,更新则返回200和当前更新文件
2
3
4
5
6
7
8
9
10
11
有了Last-Modified,为什么还要用ETag? 1、因为如果在一秒钟之内对一个文件进行两次更改,Last-Modified就会不正确(Last—Modified不能识别秒单位的修改) 2、某些服务器不能精确的得到文件的最后修改时间 3、一些文件也行会周期新的更改,但是他的内容并不改变(仅仅改变修改的事件),这个时候我们并不希望客户端认为文件被修改,而重新Get
from memory cache 与 from disk cache 从浏览器控制台Network中size一栏通常会有三种状态
- memory cache
- disk cache
- 资源自身大小(如:2k)
区别
- Service Worker:是运行在浏览器背后的独立线程,一般可以用来实现缓存功能,传输协议必须为 HTTPS,他的缓存与浏览器其他内建的缓存机制不同,它可以让我们自由控制缓存哪些文件、如何匹配缓存、如何读取缓存,并且缓存是持续性的。
- memory cache(短期缓存):从内存中,资源直接从内存中拿到,不会请求服务器,一般已经加载过该资源且缓存在内存中了。当关闭页面时,此资源就被内存释放掉,再次从新打开页面时不会出现 memory cache 的情况
- disk cache:资源从磁盘中获取,也是在已经在之前的某个时间加载过该资源,不会请求服务器但是此资源不会随着该页面的关闭而释放掉,因为是存在硬盘当中的,下次打开仍会from disk cache
- 资源自身大小:当http 状态码是200时,表示从服务器获取的资源,当状态码为304时,表示该数字是与服务端通信报文的大小,并不是该资源本身的大小,该资源是从本地获取的
状态码 | 类型 | 说明 |
---|---|---|
200 | memory cache | 不请求网络资源,资源存在内存中,一般为脚本,图片字体 |
200 | disk cache | 不请求网络资源,资源存在磁盘中,一般非脚本会存在内存当中,如css等。 |
200 | 资源自身大小 | 资源大小数值 从服务器下载最新资源。 |
304 | 报文大小 | 请求服务端发现资源没有更新,使用本地资源,即命中协商缓存 |
三级缓存原理
- 先查找内存,存在则从内存中加载
- 内存中未找到,选择磁盘里获取,如磁盘有从磁盘加载
- 磁盘未找到,就发送网络请求
- 加载到的资源缓存到磁盘或内存中
hrome会根据本地内存的使用率来决定缓存存放在哪,如果内存使用率很高,放在磁盘里面,内存的使用率很高会暂时放在内存里面。这就可以比较合理的解释了为什么同一个资源有时是from memory cache有时是from disk cache的问题了
# session 与 cookie
1,session 在服务器端,cookie 在客户端(浏览器) 2,session 默认被存在在服务器的一个文件里(不是内存) 3,session 的运行依赖 session id,而 session id 是存在 cookie 中的,也就是说,如果浏览器禁用了 cookie ,同时 session 也会失效(但是可以通过其它方式实现,比如在 url 中传递 session_id) 4,session 可以放在 文件、数据库、或内存中都可以。 5,用户验证这种场合一般会用 session 因此,维持一个会话的核心就是客户端的唯一标识,即 session id
session 与 cookie (opens new window)
# http协议详解
当我们在浏览器地址栏输入我们要访问的 URL 后,浏览器会分析出URL上面的域名,然后通过DNS服务器解析出域名映射的IP地址,浏览器根据查询到的IP地址与Web服务器进行通信.
而用于客户端与服务器之间的通信协议就是我们今天要研究的 HTTP 协议。如果想了解从输入 URL 到页面呈现背后发生的故事,可以戳这里
http是TCP/IP协议族的一部分
# HTTP 是无状态协议
为了更快地处理大量事务,确保协议的可伸缩性, HTTP 协议被设计成无状态协议。
HTTP 协议自身不会对请求和响应之间的通信状态进行保存。任何两次请求之间都没有依赖关系。直观地说,就是每个请求都是独立的,与前面的请求和后面的请求都是没有直接联系的。协议本身并不保留之前一切的请求或 响应报文的信息,换言之协议对于发送过的请求或者响应都不做持久化处理。
# UDP 和 TCP
UDP:协议面向无连接,不需要在传输数据前先连接对方,缺点:因此他具有不可靠性,不保证数据有序且不丢失的传递到对端,优点:相比TCP更轻便高效
TCP:面向无连接,断开和连接都需要先握手,并在数据传输过程中,通过算法来保证数据的可靠性,基于字节流(将大块数据分割为以报文段为单位的数据包进行管理)
# HTTP和TCP的不同
HTTP 作用是去定义数据,它规定在两台计算机之间相互传递信息时,每段数据以什么形式表达才能够被另一台计算机接收
TCP 作用是数据怎样才能稳定高效的在计算机之间传递
# TCP的三次握手和四次挥手
握手过程:
发送端 => 接收端 你能听到吗,下班去吃火锅?
接收端 => 发送端 能的,你能听到我吗,去哪吃?
发送端 => 接收端 可以的,记得带上钱。
具体过程:
发送端发送当前seq(发送端序号)x 发送给当前接收端(发送SYN表识数据包)
接收端返回ack(确认序号)x+1,seq(接收端序号) y 给发送端(发送SYN表识数据包)
发送单发送ack(确认序号)y+1给接收端(发送ACK表识数据包)
挥手过程:
客户端 => 服务端 请求关闭连接
服务端 => 客户端 好的,收到关闭消息
服务端 => 客户端 我要关闭了,你确认下
客户端 => 服务端 我关闭了,你也关闭吧,不用回复了
具体过程
客户端发送seq x+2(序号)ACK y+1 (确认序号)给服务端(FIN包)
服务器发送ACK(确认序号)x+1(ACK包)
服务器发送seq y+1 (序号)(FIN包)
客户端发送ACK(确认序号)y+2
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
TCP三次握手和四次挥手的存在意义 为什么三次握手
三次握手是为了确保客户端和服务端双方的接收与发送能力是否正常
,至于为什么不是不是两次,四次,是因为为了避免不必要的性能的开销,而3次,是完成双方考察发送和接收能力的最少次数。两次的话无法确认客户端的接收能力
为什么四次挥手
由于 tcp 是双向的,当我们客户端发送给服务端说可以断开连接了,但这个时候我们服务端数据可能还没发送完,所以需要进行一次确认。我们服务端发送一个我收到了的消息(ACK确认包)给客户端,然后服务端再发送一个我已经传输完毕了的消息(FIN包),可以断开链接了,然后客户端确认到关闭端请求,给服务端发送收到端消息,双方就关闭了
# URI编码规则
URL编码只是简单的在特殊字符的各个字节前加上%,例如,我们对上述会产生奇异的字符进行URL编码后结果:“name1=va%26lu%3D”,这样服务端会把紧跟在“%”后的字节当成普通的字节,就是不会把它当成各个参数或键值对的分隔符。
通常如果一样东西需要编码,说明这样东西并不适合传输。原因多种多样,如Size过大,包含隐私数据,对于Url来说,之所以要进行编码,是因为Url中有些字符会引起歧义。
例如,Url参数字符串中使用key=value键值对这样的形式来传参,键值对之间以&符号分隔,如/s?q=abc&ie=utf-8。如果你的value字符串中包含了=或者&,那么势必会造成接收Url的服务器解析错误,因此必须将引起歧义的&和=符号进行转义,也就是对其进行编码。
又如,Url的编码格式采用的是ASCII码,而不是Unicode,这也就是说你不能在Url中包含任何非ASCII字符,例如中文。否则如果客户端浏览器和服务端浏览器支持的字符集不同的情况下,中文可能会造成问题。