当前位置: 移动互联网学院 > Android开发 > Http简介
Http简介 时间:2017-05-17     来源:移动互联网学院

一、HTTP协议简介

HTTP(HyperText Transfer Protocol)超文本传输协议,是互联网上应用为广泛的网络通信协议。比如,我们通过浏览器访问网页就是在使用HTTP通信协议在和远端的服务器进行网络通信。 

HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。

1.1 URL

URL(Uniform Resource Locator)对象代表统一资源定位器,它是指向互联网资源的指针。URL由协议名、主机、端口和资源组成: 

protocol://host:port/resource

protocol表示要定位网络资源的协议;

host表示合法的Internet主机域名或者IP地址;

port指定一个端口号,为空则使用缺省端口80;

resource指定请求资源的URI;

例如://192.168.1.1:8080/a.jpg,该url表示192.168.2.1主机上的a.jpg资源。

1.2 请求类型

HTTP常用请求类型 

1. GET:用来获取服务器的资源(使用浏览器访问网站) 

2. POST:向服务器提交数据(提交用户名和密码)

1.3 HTTP之请求消息Request

客户端发送一个HTTP请求到服务器的请求消息包括以下格式: 

请求行(request line)、请求头部(header)、空行和请求数据四个部分组成。 

 

Get请求例子,使用Charles抓取的request: 

GET /562f25980001b1b106000338.jpg HTTP/1.1 

Host  img.mukewang.com 

User-Agent  Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36 

Accept  image/webp,image/,/*;q=0.8 

Referer  //www.imooc.com/ 

Accept-Encoding  gzip, deflate, sdch 

Accept-Language  zh-CN,zh;q=0.8 

第一部分:请求行,用来说明请求类型,要访问的资源以及所使用的HTTP版本. 

GET说明请求类型为GET,[/562f25980001b1b106000338.jpg]为要访问的资源,该行的后一部分说明使用的是HTTP1.1版本。 

第二部分:请求头部,紧接着请求行(即第一行)之后的部分,用来说明服务器要使用的附加信息 

从第二行起为请求头部,HOST将指出请求的目的地.User-Agent,服务器端和客户端脚本都能访问它,它是浏览器类型检测逻辑的重要基础.该信息由你的浏览器来定义,并且在每个请求中自动发送等等 

第三部分:空行,请求头部后面的空行是必须的 

即使第四部分的请求数据为空,也必须有空行。 

第四部分:请求数据也叫主体,可以添加任意的其他数据。 

这个例子的请求数据为空。 

POST请求例子,使用Charles抓取的request: 

POST / HTTP1.1 

Host:www.wrox.com 

User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022) 

Content-Type:application/x-www-form-urlencoded 

Content-Length:40 

Connection: Keep-Alive

 

第一部分:请求行,第一行明了是post请求,以及http1.1版本。 

第二部分:请求头部,第二行至第六行。 

第三部分:空行,第七行的空行。 

第四部分:请求数据,第八行。

 

1.4 HTTP之响应消息Response

 

一般情况下,服务器接收并处理客户端发过来的请求后会返回一个HTTP的响应消息。 

HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。 

  

第一部分:状态行,表明协议版本、状态码、状态消息 

第二部分:消息报头,说明一些客户端要使用的附加信息,如文本类型、字符集等等 

第三部分:空行 

第四部分:响应正文,服务器返回的文本数据

 

常见状态代码、状态描述、说明: 

(1) 200 OK 客户端请求成功 

(2) 400 Bad Request 客户端请求有语法错误,不能被服务器所理解 

(3) 401 Unauthorized 请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 

(4) 403 Forbidden 服务器收到请求,但是拒绝提供服务 

(5) 404 Not Found 请求资源不存在,eg:输入了错误的URL 

(6) 500 Internal Server Error 服务器发生不可预期的错误 

(7) 503 Server Unavailable 服务器当前不能处理客户端的请求,一段时间后,可能恢复正常

 

1.5 HTTP 请求/响应的步骤

1、客户端连接到Web服务器 

一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。例如,//www.oakcms.cn。

2、发送HTTP请求 

通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。

3、服务器接受请求并返回HTTP响应 

Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。

4、释放连接TCP连接 

若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;

5、客户端浏览器解析HTML内容 

客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。

 

二、HTTP实现

Android使用Java,对于Http协议的基本功能有两种实现方案,使用JDK的java.NET包下的HttpURLConnection和使用Apache的HttpClient。 

HttpClient是apache的开源实现,而HttpUrlConnection是安卓标准实现,安卓SDK虽然集成了HttpClient,但官方支持的却是HttpUrlConnection。虽然HttpClient更好地支持很多细节的控制(如代理、COOKIE、鉴权、压缩、连接池),但相应地对开发人员要求更高,代码写起来更复杂,普通开发人员很难做到对它很好地驾驭,官方的支持也越来越少,在5.1版本及以上已经将其废弃;而HttpUrlConnection对大部分工作进行了包装,屏蔽了不需要的细节,更适合开发人员直接调用,而且官方对它的支持和优化也会越来越好。我们既然是做安卓应用的开发,自然要遵循安卓官方的指引,选用HttpUrlConnection。

2.1HttpClient提交http请求

2.1.1 GET方式

(1)创建HttpClient对象 

HttpClient client = new DefaultHttpClient() 

(2)创建GET请求对象 

HttpGet reqGet = new HttpGet(url) 

(3)发送请求,获取响应 

HttpResponse rsp = client.execute(reqGet) 

(4)判断响应中的状态码(可选) 

rsp .getStatusLine().getStatusCode() 

(5)获取响应对象中的通信实体 

HttpEntity entity = rsp.getEntity() 

(6)从通信实体中获取输入流,并读取来自服务器的数据 

InputStream is = entity.getContent() 

Get请求的参数会跟在url后进行传递,请求的数据会附在URL之后,以?分割URL和传输数据: 

例如://192.168.1.112:8080/Httpserver/MySevlet?name=lr&pwd=123

2.1.2 POST方式

(1)创建HttpClient对象 

HttpClient client = new DefaultHttpClient() 

(2)创建POST请求对象 

HttpPost reqPost = new HttpPost(url) 

(3)创建要提交的键值对数据,并作为Entity设置给POST请求 

//创建数组保存需要提交的键值对 

ArrayList params = new ArrayList(); 

//添加键值对 

params.add(new BasicNameValuePair(“key”, “value”)); 

//将键值对封装到Entity对象中,并设置给POST请求 

reqPost .setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); 

(4)发送请求,获取响应 

HttpResponse rsp = client.execute(reqPost ) 

(5)判断响应中的状态码(可选) 

rsp .getStatusLine().getStatusCode() 

(6)获取响应对象中的通信实体 

HttpEntity entity = rsp.getEntity() 

(7)从通信实体中获取输入流,并读取来自服务器的数据 

InputStream is = entity.getContent() 

Get传输的数据有大小限制,传递的参数在url中,若被劫取则容易泄露,所以Get方式不适用于敏感信息的上传。Post没有限制提交的数据,Post比Get安全,上传的参数不在url中。

 

2. HttpURLConnection提交http请求

2.2.1 GET方式

(1)创建URL对象 

URL url = new URL(path); 

(2)创建HttpURLConnection对象 

HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 

(3)建立连接获取输入流,读取来自服务器的数据 

InputStream is =conn.getInputStream();

2.2.2 POST方式

(1)创建URL对象 

URL url = new URL(path); 

(2)创建HttpURLConnection对象 

HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 

(3)设置请求类型,默认为GET 

conn.setRequestMethod(“POST”); 

(4设置可输出 

conn.setDoOutput(true); 

(5)发送数据 

conn.getOutputStream().write(param.getBytes()); 

(6) 获取输入流接,读取来自服务器的数据 

InputStream in = conn.getInputStream();