背景:
前面我们已经了解过回顾过TCP/IP相关知识了。但是作为Android开发,很多人实际上正面接触传输层的TCP协议的机会并不是很多。大部分时候我们接触的最多的还是应用层的HTTP和HTTPS协议。所以这篇我们就来聊一聊HTTP和HTTPS。
一、HTTP协议
HTTP协议又称应用层超文本传输协议。
1.1、HTTP URL解析与报文结构
1.1.1、URL解析
我们常常访问一个网页,发现又一大串如下的字符串。而这一大串字符串就是HTTP网络请求的URL,如下:
http://www.baidu.com/index.html?name=3342&key=54324#mao=32134
- http:// 表示协议protocol
- www.baidu.com 主机域名(会通过DNS解析,将域名转换成IP地址)
- index.html 路劲path
- ?name=3342&key=54324 参数query
- #mao=32134 锚 用来指定页面某个位置的
当我们访问这个URL时,浏览器就会通过解析这个URL完成HTTP请求来访问对应的网页数据。
1.1.2、HTTP报文结构
每一次的HTTP请求的都会发送一个HTTP报文,如下:
- 请求行:请求的方法、目标地址、以及HTTP协议版本
- 请求头:也叫header,包含属性的一些附加信息,比如我们下面要讲的缓存机制相关的规则信息就包含在请求头中。
- 请求体:也叫body,这一部分就是我们真正的请求数据。
1.2、一次HTTP请求的完整流程
一次完整的HTTP网络请求都会经过下面的流程:
- 首先进行DNS域名解析
- 三次握手建立TCP连接
- 客户端向服务器发送请求命令 (请求行),如:Get /www/xx/com HTTP/1.1
- 服务端响应100-continue,表示接收请求
- 客户端发送请求头和请求体信息
- 服务器接收到请求后,应答 HTTP/1.1 200 OK
- 返回响应头信息,向客户端发送数据
- 服务器关闭TCP连接
1.3、HTTP常见请求方式的区别
Android开发我们最常见的两种请求方法就是GET和POST。但是我们很多时候只知道后台开发人员告诉我们要用GET或POST来发送请求而已,并不知道这个两个方法到底有什么区别。
但是面试的时候偶尔还是会被问到这个两个方法有啥区别。所以我们就来讲一讲他们之前的异同点。
(1)相同
GET和POST都是基于TCP来发送数据包
(2)区别
- GET请求的参数时通过URL传递的,而POST请求的参数是通过RequestBody来传递
- GET请求会被浏览器主动缓存(cache),而POST请求则不会,除非手动设置缓存机制
- GET请求参数会被完整的保留再浏览器的历史记录中,而POST请求的参数不会被保留
- GET请求中如果有非ASCII字符,会在请求之前进行转码,但是POST不用,因为POST请求会通过RequestBody的MIME传输非 ASCII 字符。
- GET请求只会发送一个TCP数据包,一次性将header和data发送出去。而POST会产生两个TCP数据包,先发送header,服务器响应100continue之后再发送data数据包。在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。
1.4、HTTP的缓存机制
上面我们也说了,GET请求浏览器会主动cache,POST需要手动设置才会有缓存机制。那么什么是HTTP的缓存机制呢?
我们可以简单认为浏览器存在一个缓存数据库,用于存储缓存信息。当客户端第一次请求数据时,此时缓存数据库中没有对应的缓存数据,需要请求服务器,服务器返回后,将数据存储至缓存数据库中。
HTTP的缓存规则有很多种,大致可分为:强制缓存、对比缓存两种,而HTTP中这两种缓存规则是同时存在的。且强制缓存优先级高于对比缓存,也就是说,当执行强制缓存的规则时,如果缓存生效,直接使用缓存,不再执行对比缓存规则。
(1)强制缓存
我们知道,在没有缓存数据的时候,浏览器向服务器请求数据时,服务器会将数据和缓存规则一并返回,缓存规则信息就包含在响应header中。对于强制缓存来说,响应header中会有两个字段来标明强制缓存的规则(Expires/Cache-Control),也就是会根据这两个字段来判断强制缓存是否生效。基于强制缓存的请求数据流程如下:
如图我们知道强制缓存规则,在缓存数据未失效的情况下,可以直接使用缓存数据,那么浏览器是如何根据字段Expires/Cache-Control判断缓存数据是否失效呢?
Expires
Expires的值为服务端返回的到期时间,即下一次请求时,请求时间小于服务端返回的到期时间,直接使用缓存数据。
不过Expires 是HTTP 1.0的东西,现在默认浏览器均默认使用HTTP 1.1,所以它的作用基本忽略。另一个问题是,到期时间是由服务端生成的,但是客户端时间可能跟服务端时间有误差,这就会导致缓存命中的误差。所以HTTP 1.1 的版本,使用Cache-Control替代。
Cache-Control
Cache-Control 是最重要的规则。常见的取值有private、public、no-cache、max-age,no-store,默认为private。Cache-Control的取值也可以设置多种组合。
- private: 客户端可以缓存
- public: 表明响应可以被任何对象(包括:发送请求的客户端,代理服务器等等)缓存,即使是通常不可缓存的内容。(前端的同学,可以认为public和private是一样的)
- max-age=xxx: 缓存的最大存活时间,超过这个时间缓存被认为过期(单位秒),即缓存的内容将在 xxx 秒后失效。
- no-cache: 需要使用对比缓存来验证缓存数据,在使用缓存之间先与服务器进行对比缓存
- no-store: 所有内容都不会缓存,强制缓存,对比缓存都不会触发(对于想使用缓存机制来说,当然缓存越多越好,so...基本上和它说886)
(2)对比缓存
和强制缓存类似客户端在第一次请求数据时服务器返回的数据和缓存规则中还会携带两个标识用于对比缓存:
- Last-Modified:表示最后一次修改资源的时间
- Etag :表示资源的唯一ID
首先我们来看看服务器响应头中的Last-Modified
- 当客户端触发对比缓存时,会向服务器发送标识(If-Modified-Since:表示上一次Last-Modified返回的值)
- 服务器收到请求后发现有头If-Modified-Since 则与被请求资源的最后修改时间进行比对。
- 若资源的最后修改时间大于If-Modified-Since,说明资源又被改动过,则响应整片资源内容,返回状态码200,且Response会携带新的缓存规则
- 若资源的最后修改时间小于或等于If-Modified-Since,说明资源无新修改,则响应HTTP 304,告知缓存有效。
与Last-Modified类似,如果缓存规则中存在Etag 标识,则优先使用Etag 来与服务器进行对比(即Etag 的优先级比Last-Modified要高):
- 当客户端触发对比缓存时,如果存在Etag标识,则会向服务器发送标识(If-None-Match:表示上一次Etag返回的值)
- 服务器收到请求后发现有头If-None-Match 则与被请求资源的唯一标识进行比对。
- 若资源资源ID不同,说明资源又被改动过,则响应整片资源内容,返回状态码200,且Response会携带新的缓存规则
- 若资源ID相同,说明资源无新修改,则响应HTTP 304,告知缓存有效。
基于对比缓存的请求数据流程如下:
通过上述可知对比缓存在本地存在缓存标识的情况下,会和服务器进行标识比较来确定本地缓存数据是否有效。如果有效服务器则会返回304表示缓存有效,如果无效则服务器会返回新的数据和缓存规则。
二、HTTPS协议
HTTP协议是超文本协议,那么也就是明文协议,如同上图通过抓包工具我们就能够轻松获取到请求和响应数据。那么问题随之而来了,这样的明文协议对一些企业业务的风险是很大的:
- 窃听风险:第三方可以获取通信内容
- 篡改风险:第三方可以拦截修改通信内容
- 冒充风险:第三方可以冒充他人身份参与通信
所以为了解决这些风险HTTPS设计就来了:
- 加密:所有信息是加密传输,第三方无法窃听
- 校验:具有校验机制,一旦被篡改,通信双方能够立刻发现
- 证书:配备CA身份证书,防止身份被冒充
为了解决HTTP面临的风险,HTTPS实际上是在HTTP的通信流程中加入了一加解密和认证的过程。
2.1、HTTPS的加密
在HTTPS建立通信的流程中会涉及到两种加密方式:
- 对称加密:双方都使用相同的密钥来解析密文(如:DES、AES等。),优点是计算量小,速度快,加密效率高。
- 非对称加密:加密使用公钥,解密使用私钥 ,或者加密使用私钥,解密使用公钥(如:RSA算法),优点是更加安全,但是速度慢。
在加密算法中,我们常接触到的除了对称加密和非对称加密外,还有一种加密方式也常碰到:MD5加密,且MD5加密有他自己的特点:
- 加密数据不可逆
- 加密过程不需要密钥参与
- 加密后字符串会变小
2.2、HTTPS的认证流程
HTTPS的认证分为两种:单向认证和双向认证
单向认证:所谓的单向就是只需要客户端对服务器的证书是否有效
双向认证: 而双向认证则需要客户端和服务器两端的证书相互认证
总结:
- 不管是单向认证还是双向认证,客户端都会向服务器获取并验证公钥(如果是双向认证就多出一步客户端将自己的公钥发送给服务端进行一个公钥交换)
- 双方证书验证通过并协商好加密方式后,客户端会生成一个随机码,然后用服务端的公钥加密作为后续通信时对称加密的密钥。
- 双方确认对称加密的密钥后,即可进行数据通信了。
注意:公钥是在证书里面的,而证书是需要进过认证的,这也就确保了公钥不会被篡改。
三、HTTP各版本之间的区别
这个问题一般面试的时候经常会碰到。所以这里提一嘴。
(1)、HTTP1.1 和HTTP1.0的主要区别
- 1.1在1.0的基础上增加了keepAlive,一次TCP连接可多次请求
- 1.1在1.0基础上增加了缓存特性,引入了Cache-Control用来解决Expires缓存的缺陷
- 1.1在1.0基础上增加了PUT、DELETE、OPTIONS等方法
(2)、 HTTP2.0的主要区别