Appearance
http
http 协议特点
- 1、
简单快速
:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有 GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于 HTTP 协议简单,使得 HTTP 服务器的程序规模小,因而通信速度很快。 - 2、
灵活
:HTTP 允许传输任意类型的数据对象。正在传输的类型由 Content-Type 加以标记。 - 3.
无连接
:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。 - 4.
无状态
:HTTP 协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。 - 5、支持
B/S及C/S
模式。
http 报文的组成部分
第一部分:请求行,用来说明请求类型,要访问的资源以及所使用的 HTTP 版本.
GET 说明请求类型为 GET,[/hu.jpg]为要访问的资源,该行的最后一部分说明使用的是 HTTP1.1 版本。
第二部分:请求头部,紧接着请求行(即第一行)之后的部分,用来说明服务器要使用的附加信息
从第二行起为请求头部,HOST 将指出请求的目的地.User-Agent,服务器端和客户端脚本都能访问它,它是浏览器类型检测逻辑的重要基础.该信息由你的浏览器来定义,并且在每个请求中自动发送等等
第三部分:空行,请求头部后面的空行是必须的
即使第四部分的请求数据为空,也必须有空行。
第四部分:请求数据也叫主体,可以添加任意的其他数据。
这个例子的请求数据为空。
HTTP 之状态码
- 1xx:指示信息--表示请求已接收,继续处理
- 2xx:成功--表示请求已被成功接收、理解、接受
- 3xx:重定向--要完成请求必须进行更进一步的操作
- 4xx:客户端错误--请求有语法错误或请求无法实现
- 5xx:服务器端错误--服务器未能实现合法的请求
常见状态码:
- 200 OK
客户端请求成功
- 400 Bad Request
客户端请求有语法错误,不能被服务器所理解
- 401 Unauthorized
请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
- 403 Forbidden
服务器收到请求,但是拒绝提供服务
- 404 Not Found
请求资源不存在,eg:输入了错误的URL
- 500 Internal Server Error
服务器发生不可预期的错误
- 503 Server Unavailable
服务器当前不能处理客户端的请求,一段时间后可能恢复正常
- 201: 已创建
- 202: 已接受
- 203: 成为,但未授权
- 204: 成功,无内容
- 205: 成功,重置内容
- 206: 成功,部分内容
断点续传
- 301: 永久移动,重定向
- 302: 临时移动,可使用原有 URI
- 304: 资源未修改,可使用缓存
- 305: 需代理访问
GET、POST 区别
- GET 请求会被浏览器主动缓存,POST 不会,除非手动设置
- GET 请求参数在 URL 中是会限制的,POST 没有限制
- GET 请求参数在 URL 中,POST 放在 request body 中
什么是长连接、短连接
- 在 HTTP/1.0 中默认使用短连接。也就是说,客户端和服务器每进行一次 HTTP 操作,就建立一次连接,任务结束就中断连接。当客户端浏览器访问的某个 HTML 或其他类型的 Web 页中包含有其他的 Web 资源(如 JavaScript 文件、图像文件、CSS 文件等),每遇到这样一个 Web 资源,浏览器就会重新建立一个 HTTP 会话。
- 而从 HTTP/1.1 起,默认使用长连接,用以保持连接特性。使用长连接的 HTTP 协议,会在响应头加入这行代码:
Connection:keep-alive
- 在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。Keep-Alive 不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如 Apache)中设定这个时间。实现长连接需要客户端和服务端都支持长连接。
- HTTP 协议的长连接和短连接,实质上是 TCP 协议的长连接和短连接。
http 缓存架构图
Last-Modified & Etag
TIP
- Last-Modified 文件最后修改的时候
- ETag 的值服务端是对文件的索引节,大小和最后修改时间进行 Hash 后得到的
有了 Last-Modified,为什么还要用 ETag?
(1)因为如果在一秒钟之内对一个文件进行两次更改,Last-Modified 可能就会不正确。
(2)某些服务器不能精确的得到文件的最后修改时间。
(3)一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新 GET。
有了 Etag,为什么还要用 Last-Modified ?
因为有些时候 ETag 可以弥补 Last-Modified 判断的缺陷,但是也有时候 Last-Modified 可以弥补 ETag 判断的缺陷,比如一些图片等静态文件的修改,如果每次扫描内容生成 ETag 来比较,显然要比直接比较修改时间慢很多。所有说这两种判断是相辅相成的。
强缓存 & 协商缓存
TIP
强缓存时间未过期不会主动向服务器发请求 Cache-Control/Expires: 浏览器判断缓存是否过期,未过期时,直接使用强缓存,Cache-Control 的 max-age 优先级高于 Expires Etag 的优先级高于 Last-Modified
强缓存
cache-control
max-age 浏览器缓存时间,时间未过期直接读取浏览器缓存
s-max-age CND 缓存时间 s-max-age 大于 max-age,所有先读取 CND
private 私有的缓存一般存在浏览器
public 公共的缓存一般存在 CND 服务器
no-store 禁用缓存
expires 缓存过期时间 max-age 大于 expires,所有先看 max-age
协商缓存
Last-Modified 服务器资源最后一次修改的时间 存在 response
If-Modified-Since 服务器资源最后一次修改的时间 存在 requset 浏览器请求的时候会带上 if-modified-since 时间,服务器经过对比时间相同返回 304 读取浏览器缓存,不同返回 200 重新请求资源
Etag-None-Match response requset 都会存一个 hash 值 每次请求客户端就会带上 hash 值,服务器经过对比时间相同返回 304 读取浏览器缓存,不同返回 200 重新请求资源
刷新操作,对缓存的影响
- 正常操作-强制缓存有效,协议缓存有效
- 手动刷新(浏览器上的刷新)-强制缓存失效,协议缓存有效
- 强制刷新(ctrl + f5)-强制缓存失效,协议缓存失效
http2.0 的优势
- 采用
二进制格式传输数据
,而非 http1.1 的文本格式,二进制格式在协议的解析和优化扩展上带来更多的优势和可能 - 对消息头采用
HPACK进行压缩传输
,能够节省消息头占用的网络的流量,而 http1.1 每次请求,都会携带大量冗余头信息,浪费了很多带宽资源,头压缩能够很好的解决该问题 多路复用
,就是多个请求都是通过一个 TCP 连接并发完成,http1.1 虽然通过 pipeline 也能并发请求,但是多个请求之间的响应会被阻塞的,所以 pipeline 至今也没有被普及应用,而 http2.0 做到了真正的并发请求,同时,流还支持优先级和流量控制Server Push
,服务端能够更快的把资源推送给客户端,例如服务端可以主动把 JS 和 CSS 文件推送给客户端,而不需要客户端解析 HTML 再发送这些请求,当客户端需要的时候,它已经在客户端了。
同源策略
协议相同
、域名相同
、端口相同
跨域请求限制
TIP
跨域是浏览器的限制,和服务端无关
- Cookie localStorage 等等无法读取
- dom 无法操作
- ajax 不能发送,ajax 只能在同源下使用
那些不受同源策略的限制
- webSocket 不受同源策略的限制
- 使用 HTML5 中新引进的 window.postMessage 方法来跨域传送数据
- CORS 服务器设置 header :Access-Control-Allow-Origin
- jsonp 就是利用 script 标签不受跨越限制,让服务器端返回可执行的回调函数,得到参数
跨域请求
- 跨域如果是复杂请求会有一个
options预检机制
,预检通过成功后才会发送真正的请求 - 简单的有 get、post,其他都是复杂。如果用户添加了自定义信息也算复杂请求
- cookie 不允许跨域
跨域HTTP预检请求、嗅探请求、options请求的解决优化办法
TIP
- options(预检/嗅探请求)可能会导致请求变慢,每次进行接口请求时候,浏览器会先发出一个options请求,然后才发起正式的请求。
- 解决办法(优化):可以通过设置响应头部的
Access-Control-Max-Age
来设置预检请求有效期,即在设置的时间内只有第一次会发送出数据,下次这个接口请求(相同接口&相同参数时)不会再发出这个预检请求,而是发送真请求。
js
location /options/ {
add_header "Access-Control-Max-Age" 600;
proxy_pass http://a**********/;
}
http 对比 https
- http 是明文传输,敏感信息容易被中间劫持
- https=http+ssl 非对称加密,劫持了也无法解密
对称加密
- 加解密都是用的一个 key
非对称加密
- 会生成一对
公(Public Key)
私(Private key)
钥,用 Public Key 进行加密,Private key 解密 - Private key 不会对外公开,相对安全指数高
http2 的多路复用
在 HTTP/1 中,每次请求都会建立一次 HTTP 连接,也就是我们常说的 3 次握手 4 次挥手,这个过程在一次请求过程中占用了相当长的时间,即使开启了 Keep-Alive ,解决了多次连接的问题,但是依然有两个效率上的问题:
第一个:串行的文件传输。当请求 a 文件时,b 文件只能等待,等待 a 连接到服务器、服务器处理文件、服务器返回文件,这三个步骤。我们假设这三步用时都是 1 秒,那么 a 文件用时为 3 秒,b 文件传输完成用时为 6 秒,依此类推。(注:此项计算有一个前提条件,就是浏览器和服务器是单通道传输)
第二个:连接数过多。我们假设 Apache 设置了最大并发数为 300,因为浏览器限制,浏览器发起的最大请求数为 6,也就是服务器能承载的最高并发为 50,当第 51 个人访问时,就需要等待前面某个请求处理完成。
HTTP/2 的多路复用就是为了解决上述的两个性能问题。 在 HTTP/2 中,有两个非常重要的概念,分别是帧(frame)和流(stream)。 帧代表着最小的数据单位,每个帧会标识出该帧属于哪个流,流也就是多个帧组成的数据流。 多路复用,就是在一个 TCP 连接中可以存在多条流。换句话说,也就是可以发送多个请求,对端可以通过帧中的标识知道属于哪个请求。通过这个技术,可以避免 HTTP 旧版本中的队头阻塞问题,极大的提高传输性能。
HTTPS 中间人攻击
TIP
服务端在发送浏览器的公钥中加入 CA 证书,浏览器可以验证 CA 证书的有效性
- 1、服务器向客户端发送公钥。
- 2、攻击者截获公钥,保留在自己手上。
- 3、然后攻击者自己生成一个【伪造的】公钥,发给客户端。
- 4、客户端收到伪造的公钥后,生成加密 hash 值发给服务器。
- 5、攻击者获得加密 hash 值,用自己的私钥解密获得真密钥。
- 6、同时生成假的加密 hash 值,发给服务器。
- 7、服务器用私钥解密获得假密钥。
- 8、服务器用加密钥加密传输信息
TCP 和 UDP区别
- TCP 面向连接(如打电话要先拨号建立连接)提供可靠的服务,UDP 是无连接的,即发送数据之前不需要建立连接,UDP 尽最大努力交付,即不保证可靠交付。
- UDP 具有较好的实时性,工作效率比 TCP 高,适用于对高速传输和实时性有较高的通信或广播通信。
- 每一条 TCP 连接只能是一对一的,UDP 支持一对一,一对多,多对一和多对多的交互通信。
- UDP 分组首部开销小,TCP 首部开销 20 字节,UDP 的首部开销小,只有 8 个字节。
- TCP 面向字节流,实际上是 TCP 把数据看成一连串无结构的字节流,UDP 是面向报文的一次交付一个完整的报文,报文不可分割,报文是 UDP 数据报处理的最小单位。
- UDP 适合一次性传输较小数据的网络应用,如 DNS,SNMP 等。
为什么有非对称加密,还需要CA证书?
- 非对称密钥加密方式也存在一些问题,就是
无法证明公开密钥就是接收方公开的那个密钥
,而不是被攻击者调包的密钥。为了解决这个问题,可以使用由数字证书认证机构(CA,Certificate Authority)和其相关机关颁发的公开密钥证书
。数字证书认证机构处于客户端与服务器双方都可信赖的第三方机构的立场上
。这货就相当于是公证处,大家都相信公证处,你说你是张三别人不一定信,它说你是张三别人才能百分百信。
TCP 连接 三次握手 四次挥手
三次握手
过程
- 客户端发包,服务端收到。服务端确认:客户端的发送能力是正常的。
- 服务端发包,客户端收到。客户端确认:服务端的接收能力是正常的。
- 客户端发包,服务端收到。服务端确认:客户端即将给我发送数据,我要准备接收。
建立连接完成,然后就开始发送数据,通讯。
四次挥手
握手,是建立连接。挥手,就是告别,就是关闭连接。
过程
- 客户端发包,服务端接收。服务端确认:客户端已经请求结束
- 服务端发包,客户端接收。客户端确认:服务端已经收到,我等待它关闭
- 服务端发包:客户端接受。客户端确认:服务端已经发送完成,可以关闭
- 客户端发包,服务端接收。服务端确认:可以关闭了