HTTP是超文本转移协议,是客户端浏览器或其他程序与Web服务器之间的应用层通信协议。在Internet上的Web服务器上存放的都是超文本信息, 客户机需要通过HTTP协议传输所要访问的超文本信息。HTTP包含命令和传输信息,不仅可用于Web访问,也可以用于其他因特网/内联网应用系统之间的通信,从而实现各类应用资源超媒体访问的集成。智能终端与服务器数据交互很多都是通过http来完成的,本文对HTTP做简单介绍,并附上相关交互的代码段。
一: HTTP 交互流程
如图1所示,首先客户端发送一个请求(request)给服务器,服务器在接收到这个请求后将生成一个响应(response)返回给客户端,在客户端发送请求前需要与服务器建立链接。
图1 HTTP 交互流程
二: HTTP 交互消息结构
2.1 请求消息结构
先看请求(Request) 消息的结构, Request 消息分为3部分,第一部分叫请求行, 第二部分叫消息头, 第三部分是消息体. 消息头和消息体之间有个空行, 结构如下图
图3 响应消息结构
图2:请求消息结构
结合以下实例来分析请求消息结构
POST /app/index.php action=shows_list_json&page=1&category=%E7%94%B5%E5%BD%B1 HTTP/1.1
Content-Length: 97
Content-Type: application/x-www-form-urlencoded
Host: hybroadstore.duapp.com
Connection: Keep-Alive
User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)
showlist=%7B%22name%22%3A%22%E6%9C%80%E6%96%B0%E4%B8%8A%E6%98%A0%22%2C%22type%22%3A%22order%22%7D
红色字段为请求行,绿色字段为消息头,蓝色字段为body。
2.2 响应消息结构
响应消息的结构, 和请求消息的结构基本一样。 同样也分为三部分,第一部分叫响应行, 第二部分叫响应头,第三部分是响应实体. 头和实体之间也有个空行, 结构如下图
图3 响应消息结构
我们也结合一个实例来看响应消息结构。
HTTP/1.1 200 OK
Set-Cookie: BAEID=E2886C15C9323E442C3B0249E906607E:FG=1; path=/; version=1
Set-Cookie: PHPSESSID=recoci1rqehmf3892nd6nu3213; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-type: text/html; charset=utf-8
Date: Wed, 20 Aug 2014 02:11:50 GMT
Server: BWS/1.0
Transfer-Encoding: chunked
453
{"total":"241","shows":[{"id":"77941","youku_id":"3f51e59c589b11e3a705","title":"\u5206\u624b\u5927\u5e08","large":"http:\/\/img3.douban.com\/view\/photo\/photo\/public\/p2188112867.jpg","average":"5.7","year":"2014","info":"\u6885\u8fdc\u8d35\uff08\u9093\u8d85\u9970\uff09\u662f\u4e00\u4e2a\u60c5\u611f\u7ecf\u5386\u6781\u4e3a\u4e30\u5bcc\u7684\u7537\u4eba\uff0c\u867d\u7136\u6709\u8fc7\u8fd9\u6837\u90a3\u6837\u7684\u5931\u8d25\u604b\u60c5\uff0c\u5374\u4e5f\u5e2e\u4ed6\u94fa\u5c31\u4e86\u4e00\u6761\u901a\u5f80\u8363\u534e\u590d\u5f52\u7684\u5eb7\u5e84\u5927\u9053\u3002\u73b0\u5982\u4eca\u7684\u6885\u8fdc\u8d35\u751f\u6d3b\u5728\u9996\u90fd\u5317\u4eac\uff0c\u4e0e\u5176\u7cbe\u82f1\u56e2\u961f\u64cd\u529e\u8d77\u5e2e\u4eba\u5206\u624b\u7684\u5947\u8469\u4e1a\u52a1\uff0c\u65e0\u8bba\u4f60\u6709\u7740\u600e\u6837\u7684\u611f\u60c5\u548c\u751f\u6d3b\uff0c\u53ea\u8981\u7968\u5b50\u7ed9\u8db3\uff0c\u4ed6\u603b\u4f1a\u9ad8\u6548\u7387\u5730\u5b8c\u6210\u4efb\u52a1\u3002\u7231\u60c5\u90a3\u4e48\u865a\u5e7b\u7684\u4e1c\u897f\u592a\u4e0d\u53ef\u9760\uff0c\u8fd8\u662f\u94b1\u6700\u8ba9\u4ed6\u653e\u5fc3
红色字段为请求行,绿色字段为消息头,蓝色字段为body,注意限于篇幅,蓝色字段的消息体只摘录了部分内容。
三、请求方法介绍
Http协议定义了很多与服务器交互的方法,最基本的有4种,分别是GET,POST,PUT,DELETE. 一个URL地址用于描述一个网络上的资源,而HTTP中的GET, POST, PUT, DELETE就对应着对这个资源的查,改,增,删4个操作,参考表1。而在智能终端与服务器通信过程中常用的方法也就是GET和POST,从表1中可以看出GET方法实际上就是通过网页的URL地址实现数据的传送,而服务器端实现从URL地址中解析数据;而post方法则是通过表单的方式提交,数据采取加密方式传送,服务器接到请求后解析数据。从安全角度上看,POST方法更安全,GET方法可以直接直接提交数据。理论上将POST 没有长度限制,取决与表单的长度,而GET的长度受URL长度限制,最多是1024字节。由于POST能提交需要处理的数据,可以改变服务器上资源的请求。在本文后面会附上这两个方法的java代码请求实例。
表1 HTTP请求方法
请求方法 |
使用场景
|
GET
|
从指定资源请求数据
|
POST
|
向指定资源提交需要处理的数据
|
PUT
|
如果请求的URI是已经存在的资源,则PUT请求所附的实体应被当作修改服务器中的资源,成功的话返回200或者204。如果请求的URI资源不存在,则URI可以被定义成新的资源,这时,服务器必须通过201(建立)响应通知用户。
|
DELETE
|
要求服务器释放请求(request)中URI所指向的资源。在服务器上,DELETE方法可能会被强行制止,所以客户端不能担保操作已经实现,即使服务 器返回的状态码说明操作已经成功完成了(当然,如果服务器返回了成功,说明服务器已经打算去删除/移动需要被删除的资源了)。
|
四、响应状态介绍
Status-Code(状态码):状态码是一个三位数字,对请求(request)做出响应的类型/结果。
状态码第一位数字定义了响应类型,这里分为5种:
-1XX:Informational,请求接收到了,正在进一步的处理中。
-2XX:Success,表示用户请求被正确接收,这里典型的是:200 OK
-3XX:Redirection,表示请求没有成功,客户必须采取进一步的动作 ,典型的是302跳转。
-4XX:Client Error,表示客户端提交的请求有错误,典型的有:404 Not Found
-5XX:Server Error,表示服务器不能完成对请求的处理,典型的是:503 Service Unavailable
五、JAVA 代码实例
Android SDK 集成了Apache HttpClient模块,提供常用的HttpGet和HttpPost这两个类,分别对应Get方式和Post方式。
1. HTTP GET 代码段
2. HTTP POST 代码段
1. HTTP GET 代码段
public static String doHttpGetRequest(String url) {
String result = null;
if (TextUtils.isEmpty(url)) {
return null;
}
try {
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams
.setConnectionTimeout(httpParameters, 10 * 1000);// 设置请求超时10秒
HttpConnectionParams.setSoTimeout(httpParameters, 10 * 1000); // 设置等待数据超时10秒
HttpClient httpclient = new DefaultHttpClient(httpParameters); // 此时构造DefaultHttpClient时将参数传入
HttpGet httpRequst = new HttpGet(url);
HttpResponse httpResponse = httpclient.execute(httpRequst);// 其中HttpGet是HttpUriRequst的子类
if (httpResponse.getStatusLine().getStatusCode() == 200) {
HttpEntity httpEntity = httpResponse.getEntity();
result = EntityUtils.toString(httpEntity);// 取出应答字符串
// 一般来说都要删除多余的字符
result.replaceAll("\r", "");// 去掉返回结果中的"\r"字符,否则会在结果字符串后面显示一个小方格
}
} catch (ClientProtocolException e) {
result = e.getMessage().toString();
} catch (IOException e) {
e.printStackTrace();
result = e.getMessage().toString();
}
return result;
}
2. HTTP POST 代码段
public static String doHttpPostRequest(String url,String extraParams) {
String result =null;
List<BasicNameValuePair> pairs = new ArrayList<BasicNameValuePair>();
pairs.add(new BasicNameValuePair("post string", extraParams));
HttpPost request = new HttpPost(url);
HttpResponse response = null;
try {
request.setEntity(new UrlEncodedFormEntity(pairs, "UTF-8"));
response = new DefaultHttpClient().execute(request);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
result = EntityUtils.toString(response.getEntity(), "UTF-8");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}