Android网络编程之Http协议

一、Http协议简介

       在上一篇文章Android网络编程简介中我们说过,大部分的Android应用网络通信都是基于Http协议(超文本传输协议)的,Http协议属于应用层的协议,而应用层协议的作用是用来规定传输数据的格式,以便通信双方能够按照规则来解读数据。Http是基于TCP/IP通信协议来传递数据的,其通信依赖于传输层的TCP协议。Http协议由请求和响应组成,属于标准的客户端服务器模型。

二、Http协议在TCP/IP中的位置

      上面说过,HTTP协议是属于应用层的协议,在网络分层中,应用层属于最上面的一层,其作用是规定传输数据的格式,以便通信双方都能按照规定的格式解读数据,真正的数据传输依赖于传输层,HTTP协议通常承载于TCP协议之上,有时也承载于TLS或SSL协议层之上,这个时候就成了我们通常说的HTTPS协议。如下图所示:

三、Http协议的工作流程

      以我们平时最常见的请求Web页面举例,我们来分析Http协议的工作流程。HTTP协议定义了客户端发送请求数据的格式以及服务端返回的数据格式,通信双方只需要按照规定的格式来解析数据即可解读数据。HTTP采用请求/响应模式,客户端向服务端发送一个请求报文,请求报文的内容包括请求的方法、URL、协议版本、请求头部和请求数据;服务端以一个状态行作为响应,响应内容包括协议的版本、请求状态响应码、服务器信息、响应头部和响应内容。这中间的数据传输依赖于TCP协议。详细步骤如下:

1、客户端连接到服务器

客户端发起一个TCP连接请求,经过三次握手和服务器建立TCP连接;

2、发送请求数据

按照HTTP协议规定的格式组装请求报文,并通过TCP连接向服务端发送请求报文;

3、服务端接收请求报文并处理

服务端通过TCP连接收到客户端发送过来的请求报文后,按照规定格式解析数据,根据解读的数据生成对应的响应报文,生成的响应报文也要遵循HTTP协议;

4、服务端发送响应报文给客户端

服务端将生成的响应报文通过TCP连接发送给客户端

5、关闭TCP连接

服务端将数据发送给客户端后,如果connection模式为close,则服务端主动关闭TCP连接,客户端被动关闭连接,通信结束;如果connection模式为keepalive,则该连接会保持一段时间,则该时间段内可以继续通过连接传输数据;

6、客户端处理响应数据

客户端收到响应报文后,按照HTTP协议规定格式解析响应报文并处理。

从上面的流程可以看出,HTTP协议的主要作用是规定通信双方传输数据的格式,而真正的传输过程是有传输层的TCP连接来完成的。

四、HTTP协议数据格式解读

      由上面我们知道,HTTP协议主要的作用就是规定传输双方的数据格式。HTTP协议是基于请求/响应模式的,其报文有从客户端到服务端的请求和从服务端到客户端的响应组成。

1、请求报文格式

HTTP协议的请求报文由请求行、请求头部、空行、请求数据四个部分组成。

下面我们用postman模拟发送一个post请求,并用charles抓包查看数据格式

用charles查看请求报文数据:

POST /lotto/android/v1.0/order-group/queryOrderGroupPersonInfo HTTP/1.1
cache-control: no-cache
Postman-Token: 800ec750-6ee8-4b2b-a879-f5d854115862
Content-Type: application/json
User-Agent: PostmanRuntime/3.0.11-hotfix.2
Accept: */*
Host: sitapp.2ncai.com
accept-encoding: gzip, deflate
content-length: 38
Connection: close

{"seeType":1,"source":1,"userId":"30"}

HTTP请求报文格式如图:

请求行

请求行由请求方法、URL字段和HTTP协议版本组成,格式如下:

Method Request-URI Http-Version CRLF

CRLF表示回车和换行

在上面的例子中,请求行如下:

POST /lotto/android/v1.0/order-group/queryOrderGroupPersonInfo HTTP/1.1

HTTP请求的方法分为8种,分别是GET、POST、HEAD、PUT、DELETE、TRANCE、CONNECTON、OPTIONS。对于我们平时的开发来说,用到最多的就是GET和POST了

GET:请求获得Request-URL所标识的资源

POST:在Request-URL所标识的资源后附加新的数据,即可以向服务端发送请求数据

HEAD:请求获取Request-URL所标识的资源的响应消息报头

PUT:请求服务器存储一个资源,并用Request-URL作为其标识

DELETE:请求服务器删除Request-URL所标识的资源

TRACE:请求服务器回送收到的请求信息,主要用于测试或者诊断

CONNETC:HTTP1.1中预留的能够将连接改为管道方式的代理服务器

OPTIONS:请求查询服务器性能,或者查询与资源相关的选项或需求

请求报头

在请求行之后会有0个或者多个请求报头,每个请求报头都包含一个名字和一个值,他们之间用英文冒号(:)分隔,例如上面的例子中请求报头如下:

cache-control: no-cache
Postman-Token: 800ec750-6ee8-4b2b-a879-f5d854115862
Content-Type: application/json
User-Agent: PostmanRuntime/3.0.11-hotfix.2
Accept: */*
Host: sitapp.2ncai.com
accept-encoding: gzip, deflate
content-length: 38
Connection: close

关于请求报头我们后面说到消息报头的时候在统一说明。

空行

在HTTP协议中,规定空行是必须需要的,即使后面的请求数据为空,也必须有空行

请求数据

请求数据不在GET方法中使用,而是在POST中使用,它表示向服务器附加的请求数据。POST方法使用于需要向服务器提交数据的请求,比如客户填写表单需要提交到服务器就可以使用POST方法发起请求。

在上面例子中,请求数据如下:

{"seeType":1,"source":1,"userId":"30"}

2、响应报文的格式

HTTP的响应报文是指服务端返回给客户端的报文,响应报文的格式如下:

由上面可知,响应报文也分为四个部分:状态行、响应报文、空行、响应正文

比如上面的例子中,响应报文如下:

HTTP/1.1 200 
Date: Sat, 11 Aug 2018 04:24:25 GMT
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Connection: close
X-Application-Context: application:test:8160
Server: my_server

{"success":1,"errorCode":"10001","message":"正确","data":{"userName":"CCCC","userId":30,"headPic":"https://sitres.2ncai.com/_upload_images/user/head/1711181009252.png","winCount":32,"winAmount":2580477.84,"orderCount":249,"orderSucRate":0.36,"customizationCount":0,"winBwCount":0,"winSwCount":7,"winWCount":10,"winQCount":20,"winOtherCount":42,"orderGroupLotteryBOs":[{"lotteryCode":100,"lotteryName":"双色球","lotteryType":1,"grade":0,"orderCount":239,"orderSucRate":0.03,"winCount":3,"winAmount":324800.0},{"lotteryCode":101,"lotteryName":"七乐彩","lotteryType":1,"grade":0,"orderCount":247,"orderSucRate":1.0,"winCount":0,"winAmount":0.0},{"lotteryCode":102,"lotteryName":"大乐透","lotteryType":1,"grade":0,"orderCount":243,"orderSucRate":0.0,"winCount":0,"winAmount":0.0},{"lotteryCode":103,"lotteryName":"排列5","lotteryType":1,"grade":0,"orderCount":246,"orderSucRate":1.0,"winCount":0,"winAmount":0.0},{"lotteryCode":104,"lotteryName":"排列3","lotteryType":1,"grade":0,"orderCount":245,"orderSucRate":0.0,"winCount":0,"winAmount":0.0},{"lotteryCode":105,"lotteryName":"福彩3D","lotteryType":1,"grade":0,"orderCount":244,"orderSucRate":0.0,"winCount":0,"winAmount":0.0},{"lotteryCode":107,"lotteryName":"七星彩","lotteryType":1,"grade":0,"orderCount":249,"orderSucRate":0.0,"winCount":0,"winAmount":0.0},{"lotteryCode":300,"lotteryName":"竞彩足球","lotteryType":2,"grade":0,"orderCount":235,"orderSucRate":0.34,"winCount":30,"winAmount":1381706.71},{"lotteryCode":301,"lotteryName":"竞彩篮球","lotteryType":2,"grade":0,"orderCount":6,"orderSucRate":0.0,"winCount":0,"winAmount":0.0},{"lotteryCode":304,"lotteryName":"十四场","lotteryType":2,"grade":0,"orderCount":2,"orderSucRate":0.5,"winCount":2,"winAmount":864000.0},{"lotteryCode":305,"lotteryName":"九场胜负彩","lotteryType":2,"grade":0,"orderCount":2,"orderSucRate":0.0,"winCount":0,"winAmount":0.0},{"lotteryCode":306,"lotteryName":"北京单场","lotteryType":2,"grade":0,"orderCount":2,"orderSucRate":0.5,"winCount":2,"winAmount":9971.13}]},"serviceTime":1533961465544}

状态行

状态行的格式:HTTP-Version Status-Code Reason-Phrase CRLF

其中HTTP-Version表示服务器HTTP协议的版本,Status-Code表示响应的状态码,Reason-Phrase表示状态码的文本描述。状态码由三位数字组成,其中首位数字定义了响应的类别,且有5种类别:

100-199:指示信息,收到请求后,需要请求者继续执行操作

200-299:请求成功,请求已被成功接收并处理

300-399:重定向,要完成请求需要进行更进一步操作

400-499:客户端错误,请求有语法错误或者请求无法实现

500-599:服务端错误,服务器执行错误,无法正确处理请求

常见的状态码如下:

200 OK:客户端请求成功

400 Bad Request:客户端请求有语法错误,服务端无法理解

403 Forbidden:服务端收到请求,但是拒绝提供服务

404 NOT FOUND:服务器无法正常提供信息,或是服务器无法回应

500 Internal Server Error:服务器内部错误,无法完成请求

503 Server Unavailable:服务器当前无法处理客户端请求,一段时间后可能恢复正常

响应报头

用于传递服务器自身的信息,和请求报头对应,这个例子中的响应报头如下:

Date: Sat, 11 Aug 2018 04:24:25 GMT
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Connection: close
X-Application-Context: application:test:8160
Server: my_server

关于响应报头,我们后面统一解释

空行

在HTTP协议中,规定空行是必须需要的,即使后面的响应正文为空,也必须有空行。

响应正文

服务端返回给客户端的正文数据,在这个例子中,响应正文如下:

{"success":1,"errorCode":"10001","message":"正确","data":{"userName":"CCCC","userId":30,"headPic":"https://sitres.2ncai.com/_upload_images/user/head/1711181009252.png","winCount":32,"winAmount":2580477.84,"orderCount":249,"orderSucRate":0.36,"customizationCount":0,"winBwCount":0,"winSwCount":7,"winWCount":10,"winQCount":20,"winOtherCount":42,"orderGroupLotteryBOs":[{"lotteryCode":100,"lotteryName":"双色球","lotteryType":1,"grade":0,"orderCount":239,"orderSucRate":0.03,"winCount":3,"winAmount":324800.0},{"lotteryCode":101,"lotteryName":"七乐彩","lotteryType":1,"grade":0,"orderCount":247,"orderSucRate":1.0,"winCount":0,"winAmount":0.0},{"lotteryCode":102,"lotteryName":"大乐透","lotteryType":1,"grade":0,"orderCount":243,"orderSucRate":0.0,"winCount":0,"winAmount":0.0},{"lotteryCode":103,"lotteryName":"排列5","lotteryType":1,"grade":0,"orderCount":246,"orderSucRate":1.0,"winCount":0,"winAmount":0.0},{"lotteryCode":104,"lotteryName":"排列3","lotteryType":1,"grade":0,"orderCount":245,"orderSucRate":0.0,"winCount":0,"winAmount":0.0},{"lotteryCode":105,"lotteryName":"福彩3D","lotteryType":1,"grade":0,"orderCount":244,"orderSucRate":0.0,"winCount":0,"winAmount":0.0},{"lotteryCode":107,"lotteryName":"七星彩","lotteryType":1,"grade":0,"orderCount":249,"orderSucRate":0.0,"winCount":0,"winAmount":0.0},{"lotteryCode":300,"lotteryName":"竞彩足球","lotteryType":2,"grade":0,"orderCount":235,"orderSucRate":0.34,"winCount":30,"winAmount":1381706.71},{"lotteryCode":301,"lotteryName":"竞彩篮球","lotteryType":2,"grade":0,"orderCount":6,"orderSucRate":0.0,"winCount":0,"winAmount":0.0},{"lotteryCode":304,"lotteryName":"十四场","lotteryType":2,"grade":0,"orderCount":2,"orderSucRate":0.5,"winCount":2,"winAmount":864000.0},{"lotteryCode":305,"lotteryName":"九场胜负彩","lotteryType":2,"grade":0,"orderCount":2,"orderSucRate":0.0,"winCount":0,"winAmount":0.0},{"lotteryCode":306,"lotteryName":"北京单场","lotteryType":2,"grade":0,"orderCount":2,"orderSucRate":0.5,"winCount":2,"winAmount":9971.13}]},"serviceTime":1533961465544}

3、HTTP的消息报头

消息报头分为通用报头、请求报头、响应报头和实体报头等。消息报头由键值对组成,每行一对,关键字用“:”隔开。

通用报头

通用报头既可以出现在请求报头中,也可以出现在响应报头中,常见的通用报头如下:

Date:表示消息产生的日期和时间

Connection:允许发送指定连接的选项。例如可以指定连接是“Keep-Alive”,表示在请求完成后继续保持连接

Cache-Control:用于指定缓存指令

请求报头

请求报头用来通知服务端关于客户端的请求信息,常见的请求报头如下:

Host:请求的主机名

User-Agent:发送请求的浏览器类型、操作系统等信息

Accept:客户端可识别的内容类型列表,用于指定客户端接受哪些类型的信息

Accept-Encoding:客户端可识别的数据编码

Accept-Language:表示客户端所支持的语言类型

Transfer-Encoding:告知接收端为了保证报文的可靠传输,对报文采用了什么类型的编码方式

响应报头

响应报头用来告知客户端关于服务端的响应信息,常见的响应报头如下:

Location:用于重定向客户端到一个新的位置,常用在更换域名的时候

Server:包含服务端用来处理请求的系统信息,与请求报头中的User-Agent向对应

实体报头

实体报头用来定义被传送资源的信息,其即可用在请求也可用在响应中。常见的实体报头如下:

Content-Type:发送给接收者的实体正文的媒体类型

Content-Length:实体报文的长度

Content-Language:描述资源所用的自然语言

Content-Encoding:实体头用于压缩媒体类型。如果存在,它的值表示哪些编码应用于实体主体。它让接收端知道,如何解码以获取Content-Type标题引用的媒体类型

Last-Modified:用于指示资源的最后修改时间

Expires:用于指示资源的过期时间

五、HTTP的特点

HTTP协议的主要特点如下:

1、支持C/S(客户端/服务器)模式

2、简单快速:HTTP协议规则简单,客户端向服务器请求服务时,只需要传递请求方法和路径。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快

3、灵活:HTTP协议虽然简单,但是其功能强大,允许传递任意类型的数据对象

4、无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接,采用这种方式可以节省传输时间。(当今多数服务器支持Keep-Alive功能,使用服务器支持长连接,解决无连接的问题)

5、无状态:无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。即客户端发送HTTP请求后,服务器根据请求,会给我们发送数据,发送完后,不会记录信息。(使用cookie机制可以保持session,解决无状态的问题)

六、HTTP和HTTPS

       由于HTTP协议规则简单,功能强大,使得其被广泛使用,HTTP协议的安全性问题也越来越受到重视,由于HTTP协议只规定了传输数据的格式,其是以明文方式发送内容,不提供任何方式的数据加密,如果攻击者拦截了客户端和服务端的报文数据,就可以直接读懂其中的信息,因此,HTTP协议并不适用于敏感数据的传输。为了解决HTTP的这一缺陷,引入了HTTPS协议,HTTPS叫做安全套接字超文本传输协议,HTTPS协议是在HTTP协议的基础上加上了SSL协议,SSL依靠证书来验证服务器的身份,并为客户端和服务器之间的通信加密。

HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。

HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。

HTTPS和HTTP的区别主要如下:

1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。

3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

HTTP协议的工作流程

客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤,如图所示。

(1)客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。

(2)Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。

(3)客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。

(4)客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。

(5)Web服务器利用自己的私钥解密出会话密钥。

(6)Web服务器利用会话密钥加密与客户端之间的通信。

HTTPS协议的优点

尽管HTTPS并非绝对安全,掌握根证书的机构、掌握加密算法的组织同样可以进行中间人形式的攻击,但HTTPS仍是现行架构下最安全的解决方案,主要有以下几个好处:

(1)使用HTTPS协议可认证用户和服务器,确保数据发送到正确的客户机和服务器;

(2)HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。

(3)HTTPS是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本。

(4)谷歌曾在2014年8月份调整搜索引擎算法,并称“比起同等HTTP网站,采用HTTPS加密的网站在搜索结果中的排名将会更高”。

HTTPS协议的缺点

(1)HTTPS协议握手阶段比较费时,会使页面的加载时间延长近50%,增加10%到20%的耗电;

(2)HTTPS连接缓存不如HTTP高效,会增加数据开销和功耗,甚至已有的安全措施也会因此而受到影响;

(3)SSL证书需要钱,功能越强大的证书费用越高,个人网站、小网站没有必要一般不会用。

(4)SSL证书通常需要绑定IP,不能在同一IP上绑定多个域名,IPv4资源不可能支撑这个消耗。

(5)HTTPS协议的加密范围也比较有限,在黑客攻击、拒绝服务攻击、服务器劫持等方面几乎起不到什么作用。最关键的,SSL证书的信用链体系并不安全,特别是在某些国家可以控制CA根证书的情况下,中间人攻击一样可行。

七、总结

1、HTTP协议属于应用层的协议,其网络分层的层面来说,其主要功能是规定传输数据的格式,而真正的数据传输则交给传输层的TCP协议;

2、HTTP协议具有简单快速、灵活、无连接、无状态等特点;

3、HTTP协议传输数据是以明文的方式传输,并不提供任何方式的数据加密,为了确保敏感数据的安全性,在HTTP协议下加入了SSL协议,即构成了HTTPS协议,HTTPS协议通过证书来验证服务器的身份,并对通信数据进行加密处理;

4、HTTPS协议虽然增强了数据的安全性,但是也付出了一定的代价,比如会使页面的加载时间变长,增加耗电等;

猜你喜欢

转载自blog.csdn.net/xiao_nian/article/details/81584308