Http与Android网络请求的几种协议

HTTP深入浅出 http请求

HTTP(HyperText Transfer Protocol)是一套计算机通过网络进行通信的规则。计算机专家设计出HTTP,使HTTP客户(如Web浏览器)能够从HTTP服务器(Web服务器)请求信息和服务,HTTP目前协议的版本是1.1.HTTP是一种无状态的协议,无状态是指Web浏览器和Web服务器之间不需要建立持久的连接,这意味着当一个客户端向服务器端发出请求,然后Web服务器返回响应(response),连接就被关闭了,在服务器端不保留连接的有关信息.HTTP遵循请求(Request)/应答(Response)模型。Web浏览器向Web服务器发送请求,Web服务器处理请求并返回适当的应答。所有HTTP连接都被构造成一套请求和应答。

HTTP使用内容类型,是指Web服务器向Web浏览器返回的文件都有与之相关的类型。所有这些类型在MIME Internet邮件协议上模型化,即Web服务器告诉Web浏览器该文件所具有的种类,是HTML文档、GIF格式图像、声音文件还是独立的应用程序。大多数Web浏览器都拥有一系列的可配置的辅助应用程序,它们告诉浏览器应该如何处理Web服务器发送过来的各种内容类型。

HTTP通信机制是在一次完整的HTTP通信过程中,Web浏览器与Web服务器之间将完成下列7个步骤:

(1)    建立TCP连接

在HTTP工作开始之前,Web浏览器首先要通过网络与Web服务器建立连接,该连接是通过TCP来完成的,该协议与IP协议共同构建Internet,即著名的TCP/IP协议族,因此Internet又被称作是TCP/IP网络。HTTP是比TCP更高层次的应用层协议,根据规则,只有低层协议建立之后才能,才能进行更层协议的连接,因此,首先要建立TCP连接,一般TCP连接的端口号是80

(2)    Web浏览器向Web服务器发送请求命令

一旦建立了TCP连接,Web浏览器就会向Web服务器发送请求命令

例如:GET/sample/hello.jsp HTTP/1.1

(3)    Web浏览器发送请求头信息

浏览器发送其请求命令之后,还要以头信息的形式向Web服务器发送一些别的信息,之后浏览器发送了一空白行来通知服务器,它已经结束了该头信息的发送。

(4)    Web服务器应答

客户机向服务器发出请求后,服务器会客户机回送应答,

HTTP/1.1 200 OK

应答的第一部分是协议的版本号和应答状态码

(5)    Web服务器发送应答头信息

正如客户端会随同请求发送关于自身的信息一样,服务器也会随同应答向用户发送关于它自己的数据及被请求的文档。

(6)    Web服务器向浏览器发送数据

Web服务器向浏览器发送头信息后,它会发送一个空白行来表示头信息的发送到此为结束,接着,它就以Content-Type应答头信息所描述的格式发送用户所请求的实际数据

(7)    Web服务器关闭TCP连接

一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码

Connection:keep-alive

TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。

    

HTTP请求格式

当浏览器向Web服务器发出请求时,它向服务器传递了一个数据块,也就是请求信息,HTTP请求信息由3部分组成:

l   请求方法URI协议/版本

l   请求头(Request Header)

l   请求正文

下面是一个HTTP请求的例子:

GET/sample.jspHTTP/1.1

Accept:image/gif.image/jpeg,*/*

Accept-Language:zh-cn

Connection:Keep-Alive

Host:localhost

User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)

Accept-Encoding:gzip,deflate

username=jinqiao&password=1234

(1)       请求方法URI协议/版本

请求的第一行是“方法URL议/版本”:GET/sample.jsp HTTP/1.1

以上代码中“GET”代表请求方法,“/sample.jsp”表示URI,“HTTP/1.1代表协议和协议的版本。

根据HTTP标准,HTTP请求可以使用多种请求方法。例如:HTTP1.1支持7种请求方法:GET、POST、HEAD、OPTIONS、PUT、DELETE和TARCE。在Internet应用中,最常用的方法是GET和POST。

URL完整地指定了要访问的网络资源,通常只要给出相对于服务器的根目录的相对目录即可,因此总是以“/”开头,最后,协议版本声明了通信过程中使用HTTP的版本。

(2) 请求头(Request Header)

请求头包含许多有关的客户端环境和请求正文的有用信息。例如,请求头可以声明浏览器所用的语言,请求正文的长度等。

Accept:image/gif.image/jpeg.*/*

Accept-Language:zh-cn

Connection:Keep-Alive

Host:localhost

User-Agent:Mozila/4.0(compatible:MSIE5.01:Windows NT5.0)

Accept-Encoding:gzip,deflate.

(3) 请求正文

请求头和请求正文之间是一个空行,这个行非常重要,它表示请求头已经结束,接下来的是请求正文。请求正文中可以包含客户提交的查询字符串信息:

username=jinqiao&password=1234

在以上的例子的HTTP请求中,请求的正文只有一行内容。当然,在实际应用中,HTTP请求正文可以包含更多的内容。

HTTP请求方法我这里只讨论GET方法与POST方法

l         GET方法

GET方法是默认的HTTP请求方法,我们日常用GET方法来提交表单数据,然而用GET方法提交的表单数据只经过了简单的编码,同时它将作为URL的一部分向Web服务器发送,因此,如果使用GET方法来提交表单数据就存在着安全隐患上。例如

Http://127.0.0.1/login.jsp?Name=zhangshi&Age=30&Submit=%cc%E+%BD%BB

从上面的URL请求中,很容易就可以辩认出表单提交的内容。(?之后的内容)另外由于GET方法提交的数据是作为URL请求的一部分所以提交的数据量不能太大

l         POST方法

POST方法是GET方法的一个替代方法,它主要是向Web服务器提交表单数据,尤其是大批量的数据。POST方法克服了GET方法的一些缺点。通过POST方法提交表单数据时,数据不是作为URL请求的一部分而是作为标准数据传送给Web服务器,这就克服了GET方法中的信息无法保密和数据量太小的缺点。因此,出于安全的考虑以及对用户隐私的尊重,通常表单提交时采用POST方法。

  从编程的角度来讲,如果用户通过GET方法提交数据,则数据存放在QUERY_STRING环境变量中,而POST方法提交的数据则可以从标准输入流中获取。

HTTP应答与HTTP请求相似,HTTP响应也由3个部分构成,分别是:

l 协议状态版本代码描述

l 响应头(Response Header)

l 响应正文

下面是一个HTTP响应的例子:

HTTP/1.1 200 OK

Server:Apache Tomcat/5.0.12

Date:Mon,6Oct2003 13:23:42 GMT

Content-Length:112

<html>

<head>

<title>HTTP响应示例<title>

</head>

<body>

Hello HTTP!

</body>

</html>

协议状态代码描述HTTP响应的第一行类似于HTTP请求的第一行,它表示通信所用的协议是HTTP1.1服务器已经成功的处理了客户端发出的请求(200表示成功):

HTTP/1.1 200 OK

响应头(Response Header)响应头也和请求头一样包含许多有用的信息,例如服务器类型、日期时间、内容类型和长度等:

   Server:Apache Tomcat/5.0.12

Date:Mon,6Oct2003 13:13:33 GMT

Content-Type:text/html

Last-Moified:Mon,6 Oct 2003 13:23:42 GMT

Content-Length:112

响应正文响应正文就是服务器返回的HTML页面:

  <html>

<head>

<title>HTTP响应示例<title>

</head>

<body>

Hello HTTP!

</body>

</html>

响应头和正文之间也必须用空行分隔。  

l        HTTP应答码

   HTTP应答码也称为状态码,它反映了Web服务器处理HTTP请求状态。HTTP应答码由3位数字构成,其中首位数字定义了应答码的类型:

   1XX-信息类(Information),表示收到Web浏览器请求,正在进一步的处理中

   2XX-成功类(Successful),表示用户请求被正确接收,理解和处理例如:200 OK

3XX-重定向类(Redirection),表示请求没有成功,客户必须采取进一步的动作。

4XX-客户端错误(Client Error),表示客户端提交的请求有错误 例如:404 NOT

Found,意味着请求中所引用的文档不存在。

5XX-服务器错误(Server Error)表示服务器不能完成对请求的处理:如 500

对于我们Web开发人员来说掌握HTTP应答码有助于提高Web应用程序调试的效率和准确性。

安全连接

Web应用最常见的用途之一是电子商务,可以利用Web服务器端程序使人们能够网络购物,需要指出一点是,缺省情况下,通过Internet发送信息是不安全的,如果某人碰巧截获了你发给朋友的一则消息,他就能打开它,假想在里面有你的信用卡号码,这会有多么糟糕,幸运的是,很多Web服务器以及Web浏览器都有创立安全连接的能力,这样它们就可以安全的通信了。

通过Internet提供安全连接最常见的标准是安全套接层(Secure Sockets layer,SSl)协议。SSL协议是一个应用层协议(和HTTP一样),用于安全方式在Web上交换数据,SSL使用公开密钥编码系统。从本质讲,这意味着业务中每一方都拥有一个公开的和一个私有的密钥。当一方使用另一方公开密钥进行编码时,只有拥有匹配密钥的人才能对其解码。简单来讲,公开密钥编码提供了一种用于在两方之间交换数据的安全方法,SSL连接建立之后,客户和服务器都交换公开密钥,并在进行业务联系之前进行验证,一旦双方的密钥都通过验证,就可以安全地交换数据。

  • GET

    通过请求URI得到资源

  • POST,

    用于添加新的内容

  • PUT

    用于修改某个内容

  • DELETE,

    删除某个内容

  • CONNECT,

    用于代理进行传输,如使用SSL

  • OPTIONS

    询问可以执行哪些方法

  • PATCH,

    部分文档更改

  • PROPFIND, (wedav)

    查看属性

  • PROPPATCH, (wedav)

    设置属性

  • MKCOL, (wedav)

    创建集合(文件夹)

  • COPY, (wedav)

    拷贝

  • MOVE, (wedav)

    移动

  • LOCK, (wedav)

    加锁

  • UNLOCK (wedav)

    解锁

  • TRACE

    用于远程诊断服务器

  • HEAD

    类似于GET, 但是不返回body信息,用于检查对象是否存在,以及得到对象的元数据

apache2中,可使用Limit,LimitExcept进行访问控制的方法包括:GETPOSTPUTDELETECONNECT,OPTIONSPATCHPROPFINDPROPPATCHMKCOLCOPYMOVELOCK,
和 UNLOCK.

其中, HEAD GET POST OPTIONS PROPFIND是和读取相关的方法,MKCOL PUT DELETE LOCK UNLOCK COPY MOVE PROPPATCH是和修改相关的方法

part of Hypertext Transfer Protocol -- HTTP/1.1

RFC 2616 Fielding, et al.

9 Method Definitions

The set of common methods for HTTP/1.1 is defined below. Although this set can be expanded, additional methods cannot be assumed to share the same semantics for separately extended clients and servers.

The Host request-header field (section 14.23) MUST accompany all HTTP/1.1
requests.

9.1 Safe and Idempotent Methods

9.1.1 Safe Methods

Implementors should be aware that the software represents the user in their interactions over the Internet, and should be careful to allow the user to be aware of any actions they might take which may have an unexpected significance to themselves or others.

In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered "safe". This allows user agents to represent other methods,
such as POST, PUT and DELETE, in a special way, so that the user is made aware of the fact that a possibly unsafe action is being requested.

Naturally, it is not possible to ensure that the server does not generate side-effects as a result of performing a GET request; in fact, some dynamic resources consider that a feature. The important distinction here is that the user did not request the
side-effects, so therefore cannot be held accountable for them.

9.1.2 Idempotent Methods

Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request. The methods GET, HEAD, PUT and DELETE share this property. Also, the methods
OPTIONS and TRACE SHOULD NOT have side effects, and so are inherently idempotent.

However, it is possible that a sequence of several requests is non- idempotent, even if all of the methods executed in that sequence are idempotent. (A sequence is idempotent if a single execution of the entire sequence always yields a result that is not
changed by a reexecution of all, or part, of that sequence.) For example, a sequence is non-idempotent if its result depends on a value that is later modified in the same sequence.

A sequence that never has side effects is idempotent, by definition (provided that no concurrent operations are being executed on the same set of resources).

9.2 OPTIONS

The OPTIONS method represents a request for information about the communication options available on the request/response chain identified by the Request-URI. This method allows the client to determine the options and/or requirements associated with a
resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval.

Responses to this method are not cacheable.

If the OPTIONS request includes an entity-body (as indicated by the presence of Content-Length or Transfer-Encoding), then the media type MUST be indicated by a Content-Type field. Although this specification does not define any use for such a body, future
extensions to HTTP might use the OPTIONS body to make more detailed queries on the server. A server that does not support such an extension MAY discard the request body.

If the Request-URI is an asterisk ("*"), the OPTIONS request is intended to apply to the server in general rather than to a specific resource. Since a server‘s communication options typically depend on the resource, the "*" request is only useful as a
"ping" or "no-op" type of method; it does nothing beyond allowing the client to test the capabilities of the server. For example, this can be used to test a proxy for HTTP/1.1 compliance (or lack thereof).

If the Request-URI is not an asterisk, the OPTIONS request applies only to the options that are available when communicating with that resource.

A 200 response SHOULD include any header fields that indicate optional features implemented by the server and applicable to that resource (e.g., Allow), possibly including extensions not defined by this specification. The response body, if any, SHOULD
also include information about the communication options. The format for such a

body is not defined by this specification, but might be defined by future extensions to HTTP. Content negotiation MAY be used to select the appropriate response format. If no response body is included, the response MUST include a Content-Length field with
a field-value of "0".

The Max-Forwards request-header field MAY be used to target a specific proxy in the request chain. When a proxy receives an OPTIONS request on an absoluteURI for which request forwarding is permitted, the proxy MUST check for a Max-Forwards field. If the
Max-Forwards field-value is zero ("0"), the proxy MUST NOT forward the message; instead, the proxy SHOULD respond with its own communication options. If the Max-Forwards field-value is an integer greater than zero, the proxy MUST decrement the field-value
when it forwards the request. If no Max-Forwards field is present in the request, then the forwarded request MUST NOT include a Max-Forwards field.

9.3 GET

The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI. If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the entity in the response and not
the source text of the process, unless that text happens to be the output of the process.

The semantics of the GET method change to a "conditional GET" if the request message includes an If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match, or If-Range header field. A conditional GET method requests that the entity be transferred
only under the circumstances described by the conditional header field(s). The conditional GET method is intended to reduce unnecessary network usage by allowing cached entities to be refreshed without requiring multiple requests or transferring data already
held by the client.

The semantics of the GET method change to a "partial GET" if the request message includes a Range header field. A partial GET requests that only part of the entity be transferred, as described in section 14.35.
The partial GET method is intended to reduce unnecessary network usage by allowing partially-retrieved entities to be completed without transferring data already held by the client.

The response to a GET request is cacheable if and only if it meets the requirements for HTTP caching described in section 13.

See section 15.1.3 for security considerations when used for forms.

9.4 HEAD

The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response. The metainformation contained in the HTTP headers in response to a HEAD request SHOULD be identical to the information sent in response to a GET
request. This method can be used for obtaining metainformation about the entity implied by the request without transferring the entity-body itself. This method is often used for testing hypertext links for validity, accessibility, and recent modification.

The response to a HEAD request MAY be cacheable in the sense that the information contained in the response MAY be used to update a previously cached entity from that resource. If the new field values indicate that the cached entity differs from the current
entity (as would be indicated by a change in Content-Length, Content-MD5, ETag or Last-Modified), then the cache MUST treat the cache entry as stale.

9.5 POST

The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line. POST is designed to allow a uniform method to cover the following
functions:

- Annotation of existing resources;
- Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles;
- Providing a block of data, such as the result of submitting a form, to a data-handling process;
- Extending a database through an append operation.

The actual function performed by the POST method is determined by the server and is usually dependent on the Request-URI. The posted entity is subordinate to that URI in the same way that a file is subordinate to a directory containing it, a news article
is subordinate to a newsgroup to which it is posted, or a record is subordinate to a database.

The action performed by the POST method might not result in a resource that can be identified by a URI. In this case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on whether or not the response includes an entity that
describes the result.

If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header (see section 14.30).

Responses to this method are not cacheable, unless the response includes appropriate Cache-Control or Expires header fields. However, the 303 (See Other) response can be used to direct the user agent to retrieve a cacheable resource.

POST requests MUST obey the message transmission requirements set out in section 8.2.

See section 15.1.3 for security considerations.

9.6 PUT

The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server.
If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI. If a new resource is created, the origin server MUST
inform the user agent via the 201 (Created) response. If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request. If the resource could not be created or modified
with the Request-URI, an appropriate error response SHOULD be given that reflects the nature of the problem. The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) headers that it does not understand or implement and MUST return a 501
(Not Implemented) response in such cases.

If the request passes through a cache and the Request-URI identifies one or more currently cached entities, those entries SHOULD be treated as stale. Responses to this method are not cacheable.

The fundamental difference between the POST and PUT requests is reflected in the different meaning of the Request-URI. The URI in a POST request identifies the resource that will handle the enclosed entity. That resource might be a data-accepting process,
a gateway to some other protocol, or a separate entity that accepts annotations. In contrast, the URI in a PUT request identifies the entity enclosed with the request -- the user agent knows what URI is intended and the server MUST NOT attempt to apply the
request to some other resource. If the server desires that the request be applied to a different URI,

it MUST send a 301 (Moved Permanently) response; the user agent MAY then make its own decision regarding whether or not to redirect the request.

A single resource MAY be identified by many different URIs. For example, an article might have a URI for identifying "the current version" which is separate from the URI identifying each particular version. In this case, a PUT request on a general URI
might result in several other URIs being defined by the origin server.

HTTP/1.1 does not define how a PUT method affects the state of an origin server.

PUT requests MUST obey the message transmission requirements set out in section 8.2.

Unless otherwise specified for a particular entity-header, the entity-headers in the PUT request SHOULD be applied to the resource created or modified by the PUT.

9.7 DELETE

The DELETE method requests that the origin server delete the resource identified by the Request-URI. This method MAY be overridden by human intervention (or other means) on the origin server. The client cannot be guaranteed that the operation has been
carried out, even if the status code returned from the origin server indicates that the action has been completed successfully. However, the server SHOULD NOT indicate success unless, at the time the response is given, it intends to delete the resource or
move it to an inaccessible location.

A successful response SHOULD be 200 (OK) if the response includes an entity describing the status, 202 (Accepted) if the action has not yet been enacted, or 204 (No Content) if the action has been enacted but the response does not include an entity.

If the request passes through a cache and the Request-URI identifies one or more currently cached entities, those entries SHOULD be treated as stale. Responses to this method are not cacheable.

9.8 TRACE

The TRACE method is used to invoke a remote, application-layer loop- back of the request message. The final recipient of the request SHOULD reflect the message received back to the client as the entity-body of a 200 (OK) response. The final recipient is
either the

origin server or the first proxy or gateway to receive a Max-Forwards value of zero (0) in the request (see section 14.31). A TRACE request MUST NOT include an entity.

TRACE allows the client to see what is being received at the other end of the request chain and use that data for testing or diagnostic information. The value of the Via header field (section14.45)
is of particular interest, since it acts as a trace of the request chain. Use of the Max-Forwards header field allows the client to limit the length of the request chain, which is useful for testing a chain of proxies forwarding messages in an infinite loop.

If the request is valid, the response SHOULD contain the entire request message in the entity-body, with a Content-Type of "message/http". Responses to this method MUST NOT be cached.

9.9 CONNECT

This specification reserves the method name CONNECT for use with a proxy that can dynamically switch to being a tunnel (e.g. SSL tunneling [44]).

Android应用经常会和服务器端交互,这就需要手机客户端发送网络请求,下面介绍四种常用网络请求方式,我这边是通过Android单元测试来完成这四种方法的,还不清楚Android的单元测试的同学们请看Android开发技巧总结中的Android单元测试的步骤一文。

Java.net包中的HttpURLConnection类

Get方式:

[java] view plain copy

  1. // Get方式请求
  2. public static void requestByGet() throws Exception {
  3. String path = "https://reg.163.com/logins.jsp?id=helloworld&pwd=android";
  4. // 新建一个URL对象
  5. URL url = new URL(path);
  6. // 打开一个HttpURLConnection连接
  7. HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
  8. // 设置连接超时时间
  9. urlConn.setConnectTimeout(5 * 1000);
  10. // 开始连接
  11. urlConn.connect();
  12. // 判断请求是否成功
  13. if (urlConn.getResponseCode() == HTTP_200) {
  14. // 获取返回的数据
  15. byte[] data = readStream(urlConn.getInputStream());
  16. Log.i(TAG_GET, "Get方式请求成功,返回数据如下:");
  17. Log.i(TAG_GET, new String(data, "UTF-8"));
  18. } else {
  19. Log.i(TAG_GET, "Get方式请求失败");
  20. }
  21. // 关闭连接
  22. urlConn.disconnect();
  23. }

Post方式:

[java] view plain copy

  1. // Post方式请求
  2. public static void requestByPost() throws Throwable {
  3. String path = "https://reg.163.com/logins.jsp";
  4. // 请求的参数转换为byte数组
  5. String params = "id=" + URLEncoder.encode("helloworld", "UTF-8")
  6. + "&pwd=" + URLEncoder.encode("android", "UTF-8");
  7. byte[] postData = params.getBytes();
  8. // 新建一个URL对象
  9. URL url = new URL(path);
  10. // 打开一个HttpURLConnection连接
  11. HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
  12. // 设置连接超时时间
  13. urlConn.setConnectTimeout(5 * 1000);
  14. // Post请求必须设置允许输出
  15. urlConn.setDoOutput(true);
  16. // Post请求不能使用缓存
  17. urlConn.setUseCaches(false);
  18. // 设置为Post请求
  19. urlConn.setRequestMethod("POST");
  20. urlConn.setInstanceFollowRedirects(true);
  21. // 配置请求Content-Type
  22. urlConn.setRequestProperty("Content-Type",
  23. "application/x-www-form-urlencode");
  24. // 开始连接
  25. urlConn.connect();
  26. // 发送请求参数
  27. DataOutputStream dos = new DataOutputStream(urlConn.getOutputStream());
  28. dos.write(postData);
  29. dos.flush();
  30. dos.close();
  31. // 判断请求是否成功
  32. if (urlConn.getResponseCode() == HTTP_200) {
  33. // 获取返回的数据
  34. byte[] data = readStream(urlConn.getInputStream());
  35. Log.i(TAG_POST, "Post请求方式成功,返回数据如下:");
  36. Log.i(TAG_POST, new String(data, "UTF-8"));
  37. } else {
  38. Log.i(TAG_POST, "Post方式请求失败");
  39. }
  40. }

org.apache.http包中的HttpGet和HttpPost类

Get方式:

[java] view plain copy

  1. // HttpGet方式请求
  2. public static void requestByHttpGet() throws Exception {
  3. String path = "https://reg.163.com/logins.jsp?id=helloworld&pwd=android";
  4. // 新建HttpGet对象
  5. HttpGet httpGet = new HttpGet(path);
  6. // 获取HttpClient对象
  7. HttpClient httpClient = new DefaultHttpClient();
  8. // 获取HttpResponse实例
  9. HttpResponse httpResp = httpClient.execute(httpGet);
  10. // 判断是够请求成功
  11. if (httpResp.getStatusLine().getStatusCode() == HTTP_200) {
  12. // 获取返回的数据
  13. String result = EntityUtils.toString(httpResp.getEntity(), "UTF-8");
  14. Log.i(TAG_HTTPGET, "HttpGet方式请求成功,返回数据如下:");
  15. Log.i(TAG_HTTPGET, result);
  16. } else {
  17. Log.i(TAG_HTTPGET, "HttpGet方式请求失败");
  18. }
  19. }

Post方式:

[java] view plain copy

  1. // HttpPost方式请求
  2. public static void requestByHttpPost() throws Exception {
  3. String path = "https://reg.163.com/logins.jsp";
  4. // 新建HttpPost对象
  5. HttpPost httpPost = new HttpPost(path);
  6. // Post参数
  7. List<NameValuePair> params = new ArrayList<NameValuePair>();
  8. params.add(new BasicNameValuePair("id", "helloworld"));
  9. params.add(new BasicNameValuePair("pwd", "android"));
  10. // 设置字符集
  11. HttpEntity entity = new UrlEncodedFormEntity(params, HTTP.UTF_8);
  12. // 设置参数实体
  13. httpPost.setEntity(entity);
  14. // 获取HttpClient对象
  15. HttpClient httpClient = new DefaultHttpClient();
  16. // 获取HttpResponse实例
  17. HttpResponse httpResp = httpClient.execute(httpPost);
  18. // 判断是够请求成功
  19. if (httpResp.getStatusLine().getStatusCode() == HTTP_200) {
  20. // 获取返回的数据
  21. String result = EntityUtils.toString(httpResp.getEntity(), "UTF-8");
  22. Log.i(TAG_HTTPGET, "HttpPost方式请求成功,返回数据如下:");
  23. Log.i(TAG_HTTPGET, result);
  24. } else {
  25. Log.i(TAG_HTTPGET, "HttpPost方式请求失败");
  26. }
  27. }

二!

大家知道Google支持和发布的Android移动操作系统,主要是为了使其迅速占领移动互联网的市场份额,所谓移动互联网当然也是互联网了,凡是涉及互联网的任何软件任何程序都少不了联网模块的开发,诚然Android联网开发也是我们开发中至关重要的一部分,那么Android是怎么样进行联网操作的呢?这篇博客就简单的介绍一下Android常用的联网方式,包括JDK支持的HttpUrlConnection,Apache支持的HttpClient,以及开源的一些联网框架(譬如AsyncHttpClient)的介绍。本篇博客只讲实现过程和方式,不讲解原理,否则原理用文字很难以讲清,其实我们知道怎么去用,就可以解决一些基本开发需要了。

绝大多数的Android应用联网都是基于Http协议的,也有很少是基于Socket的,我们这里主要讲解基于Http协议的联网方式。讲解实例是建立在一个模拟的登录小模块中进行,登录请求数据仅仅只有username和password两个简单字段。

HttpUrlConnection

HttpUrlConnection是JDK里提供的联网API,我们知道Android SDK是基于Java的,所以当然优先考虑HttpUrlConnection这种最原始最基本的API,其实大多数开源的联网框架基本上也是基于JDK的HttpUrlConnection进行的封装罢了,掌握HttpUrlConnection需要以下几个步骤:

1将访问的路径转换成URL。

URL url = new URL(path);

2,通过URL获取连接。

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

3,设置请求方式。

conn.setRequestMethod(GET);

4,设置连接超时时间。

conn.setConnectTimeout(5000);

5,设置请求头的信息。

conn.setRequestProperty(User-Agent, Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0));

6,获取响应码

int code = conn.getResponseCode();

7,针对不同的响应码,做不同的操作

7.1,请求码200,表明请求成功,获取返回内容的输入流

InputStream is = conn.getInputStream();

7.2,将输入流转换成字符串信息

public class StreamTools {
	/**
	 * 将输入流转换成字符串
	 *
	 * @param is
	 *            从网络获取的输入流
	 * @return
	 */
	public static String streamToString(InputStream is) {
		try {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int len = 0;
			while ((len = is.read(buffer)) != -1) {
				baos.write(buffer, 0, len);
			}
			baos.close();
			is.close();
			byte[] byteArray = baos.toByteArray();
			return new String(byteArray);
		} catch (Exception e) {
			Log.e(tag, e.toString());
			return null;
		}
	}
}

7.3,若返回值400,则是返回网络异常,做出响应的处理。

HttpUrlConnection发送GET请求

/**
	 * 通过HttpUrlConnection发送GET请求
	 *
	 * @param username
	 * @param password
	 * @return
	 */
	public static String loginByGet(String username, String password) {
		String path = http://192.168.0.107:8080/WebTest/LoginServerlet?username= + username + &password= + password;
		try {
			URL url = new URL(path);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(5000);
			conn.setRequestMethod(GET);
			int code = conn.getResponseCode();
			if (code == 200) {
				InputStream is = conn.getInputStream(); // 字节流转换成字符串
				return StreamTools.streamToString(is);
			} else {
				return 网络访问失败;
			}
		} catch (Exception e) {
			e.printStackTrace();
			return 网络访问失败;
		}
	}

HttpUrlConnection发送POST请求

/**
	 * 通过HttpUrlConnection发送POST请求
	 *
	 * @param username
	 * @param password
	 * @return
	 */
	public static String loginByPost(String username, String password) {
		String path = http://192.168.0.107:8080/WebTest/LoginServerlet;
		try {
			URL url = new URL(path);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(5000);
			conn.setRequestMethod(POST);
			conn.setRequestProperty(Content-Type, application/x-www-form-urlencoded);
			String data = username= + username + &password= + password;
			conn.setRequestProperty(Content-Length, data.length() + );
			// POST方式,其实就是浏览器把数据写给服务器
			conn.setDoOutput(true); // 设置可输出流
			OutputStream os = conn.getOutputStream(); // 获取输出流
			os.write(data.getBytes()); // 将数据写给服务器
			int code = conn.getResponseCode();
			if (code == 200) {
				InputStream is = conn.getInputStream();
				return StreamTools.streamToString(is);
			} else {
				return 网络访问失败;
			}
		} catch (Exception e) {
			e.printStackTrace();
			return 网络访问失败;
		}
	}

HttpClient

HttpClient是开源组织Apache提供的Java请求网络框架,其最早是为了方便Java服务器开发而诞生的,是对JDK中的HttpUrlConnection各API进行了封装和简化,提高了性能并且降低了调用API的繁琐,Android因此也引进了这个联网框架,我们再不需要导入任何jar或者类库就可以直接使用,值得注意的是Android官方已经宣布不建议使用HttpClient了,我们再开发的时候尽量少用吧,但是用了也无妨!

HttpClient发送GET请求

1, 创建HttpClient对象

2,创建HttpGet对象,指定请求地址(带参数)

3,使用HttpClient的execute(),方法执行HttpGet请求,得到HttpResponse对象

4,调用HttpResponse的getStatusLine().getStatusCode()方法得到响应码

5,调用的HttpResponse的getEntity().getContent()得到输入流,获取服务端写回的数据

/**
	 * 通过HttpClient发送GET请求
	 *
	 * @param username
	 * @param password
	 * @return
	 */
	public static String loginByHttpClientGet(String username, String password) {
		String path = http://192.168.0.107:8080/WebTest/LoginServerlet?username=
				+ username + &password= + password;
		HttpClient client = new DefaultHttpClient(); // 开启网络访问客户端
		HttpGet httpGet = new HttpGet(path); // 包装一个GET请求
		try {
			HttpResponse response = client.execute(httpGet); // 客户端执行请求
			int code = response.getStatusLine().getStatusCode(); // 获取响应码
			if (code == 200) {
				InputStream is = response.getEntity().getContent(); // 获取实体内容
				String result = StreamTools.streamToString(is); // 字节流转字符串
				return result;
			} else {
				return 网络访问失败;
			}
		} catch (Exception e) {
			e.printStackTrace();
			return 网络访问失败;
		}
	}

HttpClient发送POST请求

1,创建HttpClient对象

2,创建HttpPost对象,指定请求地址

3,创建List,用来装载参数

4,调用HttpPost对象的setEntity()方法,装入一个UrlEncodedFormEntity对象,携带之前封装好的参数

5,使用HttpClient的execute()方法执行HttpPost请求,得到HttpResponse对象

6, 调用HttpResponse的getStatusLine().getStatusCode()方法得到响应码

7, 调用的HttpResponse的getEntity().getContent()得到输入流,获取服务端写回的数据

/**
	 * 通过HttpClient发送POST请求
	 *
	 * @param username
	 * @param password
	 * @return
	 */
	public static String loginByHttpClientPOST(String username, String password) {
		String path = http://192.168.0.107:8080/WebTest/LoginServerlet;
		try {
			HttpClient client = new DefaultHttpClient(); // 建立一个客户端
			HttpPost httpPost = new HttpPost(path); // 包装POST请求
			// 设置发送的实体参数
			List parameters = new ArrayList();
			parameters.add(new BasicNameValuePair(username, username));
			parameters.add(new BasicNameValuePair(password, password));
			httpPost.setEntity(new UrlEncodedFormEntity(parameters, UTF-8));
			HttpResponse response = client.execute(httpPost); // 执行POST请求
			int code = response.getStatusLine().getStatusCode();
			if (code == 200) {
				InputStream is = response.getEntity().getContent();
				String result = StreamTools.streamToString(is);
				return result;
			} else {
				return 网络访问失败;
			}
		} catch (Exception e) {
			e.printStackTrace();
			return 访问网络失败;
		}
	}

其他开源联网框架

AsyncHttpClient

除了上述Android官方推荐的联网框架以外,在开源世界里关于联网框架真是太多太多了,例如afinal,xutils等等,都是一些开源大牛自己封装的联网框架,并且在GitHub开源社区中可以下载到,其实类似的开源联网框架基本上也是基于HttpUrlConnection的进一步封装,大大提高了性能,同时更加简化了使用方法,这里使用AsyncHttpClient作为案例,其他的联网框架大家可以去网上找,下载使用试试便可。
AsyncHttpClient是一个非常优秀的联网框架,不仅支持所有Http请求的方式,而且还支持文件的上传和下载,要知道用HttpUrlConnection写一个文件上传和下载健全功能是很需要花费一定时间和精力的,因为请求头实在是太多了,稍有不慎就会写错。但是AsyncHttpClient已经封装好了这些“麻烦”,我们只需要下载到AsyncHttpClient的jar包或者源码导入项目中,Http,上传,下载等等,只需要几个简单的api即可搞定。
AsyncHttpClient的GitHub主页:https://github.com/AsyncHttpClient/async-http-client/

AsyncHttpClient发送GET请求

1,将下载好的源码拷贝到src目录下

2,创建一个AsyncHttpClient的对象

3,调用该类的get方法发送GET请求,传入请求资源地址URL,创建AsyncHttpResponseHandler对象

4,重写AsyncHttpResponseHandler下的两个方法,onSuccess和onFailure方法

/**
	 * 通过AsyncHttpClient发送GET请求
	 */
	public void loginByAsyncHttpGet() {
		String path = http://192.168.0.107:8080/WebTest/LoginServerlet?username=zhangsan&password=123;
		AsyncHttpClient client = new AsyncHttpClient();
		client.get(path, new AsyncHttpResponseHandler() {

			@Override
			public void onFailure(int arg0, Header[] arg1, byte[] arg2,
					Throwable arg3) {
				// TODO Auto-generated method stub
				Log.i(TAG, 请求失败: + new String(arg2));
			}

			@Override
			public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
				// TODO Auto-generated method stub
				Log.i(TAG, 请求成功: + new String(arg2));
			}
		});
	}

AsyncHttpClient发送POST请求

1,将下载好的源码拷贝到src目录下

2,创建一个AsyncHttpClient的对象

3,创建请求参数,RequestParams对象

4,调用该类的post方法发POST,传入请求资源地址URL,请求参数RequestParams,创建AsyncHttpResponseHandler对象

5,重写AsyncHttpResponseHandler下的两个方法,onSuccess和onFailure方法

/**
	 * 通过AsyncHttpClient发送POST请求
	 */
	public void loginByAsyncHttpPost() {
		String path = http://192.168.0.107:8080/WebTest/LoginServerlet;
		AsyncHttpClient client = new AsyncHttpClient();
		RequestParams params = new RequestParams();
		params.put(username, zhangsan);
		params.put(password, 123);
		client.post(path, params, new AsyncHttpResponseHandler() {

			@Override
			public void onFailure(int arg0, Header[] arg1, byte[] arg2,
					Throwable arg3) {
				// TODO Auto-generated method stub
				Log.i(TAG, 请求失败: + new String(arg2));
			}

			@Override
			public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
				// TODO Auto-generated method stub
				Log.i(TAG, 请求成功: + new String(arg2));
			}
		});
	}

AsyncHttpClient上传文件

1,将下载好的源码拷贝到src目录下

2,创建一个AsyncHttpClient的对象

3,创建请求参数,RequestParams对象,请求参数仅仅包含文件对象即可,例如:

params.put(profile_picture, new File(/sdcard/pictures/pic.jpg));

4,调用该类的post方法发POST,传入请求资源地址URL,请求参数RequestParams,创建AsyncHttpResponseHandler对象

5,重写AsyncHttpResponseHandler下的两个方法,onSuccess和onFailure方法

判断网络连接状态

很多时候对于手机或者平板电脑这样的手持设备,我们是不知道它们的网络连接状态的,在联网的时候我们必须得保证设备的网路是否正常,是否可以连接上互联网,或者我们在进行大量数据上传或者下载,例如下载网路视频,看网路电视等等,我们必须得为用户省钱,这样大数据的传输显然是不能使用用户昂贵的数据流量的,而是判断当前网络是不是在wifi下,使用WiFi来进行大数据的传输,会给用户更好的体验,那么下面这个工具类就是用来判断设备网络连接状态的,不仅判断了当前设置手机网络下还是WiFi环境下,而且如果手机网络下还需要设置运营商的代理IP和端口。

/**
 * 判断网络状态的工具类
 *
 */
public class NetworkUtil {

	/* 代码IP */
	private static String PROXY_IP = null;
	/* 代理端口 */
	private static int PROXY_PORT = 0;
	/**
	 * 判断当前是否有网络连接
	 *
	 * @param context
	 * @return
	 */
	public static boolean isNetwork(Context context) {
		boolean network = isWifi(context);
		boolean mobilework = isMobile(context);
		if (!network && !mobilework) { // 无网络连接
			Log.i(NetworkUtil, 无网路链接!);
			return false;
		} else if (network == true && mobilework == false) { // wifi连接
			Log.i(NetworkUtil, wifi连接!);
		} else { // 网络连接
			Log.i(NetworkUtil, 手机网路连接,读取代理信息!);
			readProxy(context); // 读取代理信息
			return true;
		}
		return true;
	}

	/**
	 * 读取网络代理
	 *
	 * @param context
	 */
	private static void readProxy(Context context) {
		Uri uri = Uri.parse(content://telephony/carriers/preferapn);
		ContentResolver resolver = context.getContentResolver();
		Cursor cursor = resolver.query(uri, null, null, null, null);
		if (cursor != null && cursor.moveToFirst()) {
			PROXY_IP = cursor.getString(cursor.getColumnIndex(proxy));
			PROXY_PORT = cursor.getInt(cursor.getColumnIndex(port));
		}
		cursor.close();
	}

	/**
	 * 判断当前网络是否是wifi局域网
	 *
	 * @param context
	 * @return
	 */
	public static boolean isWifi(Context context) {
		ConnectivityManager manager = (ConnectivityManager) context
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo info = manager
				.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
		if (info != null) {
			return info.isConnected(); // 返回网络连接状态
		}
		return false;
	}

	/**
	 * 判断当前网络是否是手机网络
	 *
	 * @param context
	 * @return
	 */
	public static boolean isMobile(Context context) {
		ConnectivityManager manager = (ConnectivityManager) context
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo info = manager
				.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
		if (info != null) {
			return info.isConnected(); // 返回网络连接状态
		}
		return false;
	}
}
时间: 2024-10-29 03:55:16

Http与Android网络请求的几种协议的相关文章

Android网络请求框架AsyncHttpClient实例详解(配合JSON解析调用接口)

最近做项目要求使用到网络,想来想去选择了AsyncHttpClient框架开进行APP开发.在这里把我工作期间遇到的问题以及对AsyncHttpClient的使用经验做出相应总结,希望能对您的学习有所帮助. 首先按照惯例先来简单了解一些AsyncHttpClient网络框架的一些知识. 1.简介 Android中网络请求一般使用Apache HTTP Client或者采用HttpURLConnect,但是直接使用这两个类库需要写大量的代码才能完成网络post和get请求,而使用android-a

Android 网络请求json数据,解析json数据,生成对应的java bean类一步到位,快速开发

Android 网络请求一般都涉及到图片和JSON数据,怎样快速的请求网络JSON数据,解析JSON数据,并且一步生成自己想要的Java bean实体类?这个涉及到Android 开发效率的问题.由于接触Android 网络这方面比较多,自然就找到一些好的方法来快速开发Android 网络模块的相关内容,接下来就为大家揭晓 一步快速请求,解析JSON 数据生成对应的Java bean实体类的方法. 注:我们先把思路讲解下吧: 1.网络请求JSON数据代码可以自己写,当然我还是推荐使用网络上开源的

【Java&amp;Android开源库代码剖析】のandroid-async-http(如何设计一个优雅的Android网络请求框架,同时支持同步和异步请求)开篇

在<[Java&Android开源库代码剖析]のandroid-smart-image-view>一文中我们提到了android-async-http这个开源库,本文正式开篇来详细介绍这个库的实现,同时结合源码探讨如何设计一个优雅的Android网络请求框架.做过一段时间Android开发的同学应该对这个库不陌生,因为它对Apache的HttpClient API的封装使得开发者可以简洁优雅的实现网络请求和响应,并且同时支持同步和异步请求. 网络请求框架一般至少需要具备如下几个组件:1

Android 网络请求及数据处理

Android 网络请求: 1.Volley   http://blog.csdn.net/t12x3456/article/details/9221611 2.Android-Async-Http   http://www.cnblogs.com/angeldevil/p/3729808.html Android Json 处理: 1.Gson 2.fast-json

浅论Android网络请求库——android-async-http

浅论Android网络请求库——android-async-http Android应用中使用AsyncHttpClient来异步网络数据

【Android】Volley做网络请求的几种用法

前言: 最近在将自己写的烂代码重构,以前使用的网络请求全是基于apache的HttpClient,简单使用还好,使用多了发现重复代码太多,而且每次使用都很繁琐,因此在网上找了半天网络请求的相关类库,最后还是确定使用Volley,于是现在记个使用笔记: Volley几个主要功能: 1. 普通String请求: 既然使用了网络请求,那么网络权限是必不可少的,在AndroidManifest.xml中添加: <uses-permission android:name="android.permi

android网络请求库volley方法详解

使用volley进行网络请求:需先将volley包导入androidstudio中 File下的Project Structrue,点加号导包 volley网络请求步骤: 1. 创建请求队列       RequestQueue queue = Volley.newRequestQueue(this); 2.创建请求对象(3种) StringRequest request = new StringRequest(“请求方法”,“请求的网络地址”,“成功的网络回调”,“失败的网络回调”): Ima

Android 网络请求方法

在Android应用开发中,我们经常会与服务器交互,获取或上传数据,这就需要用到网络请求,一般情况下是使用HTTP协议去发送和接收网络数据,而HTTP又包括两种通信方式,即:HttpUrlConnection和HttpClient. 代码例子:https://git.oschina.net/ysx_xx/HttpText/tree/master 下面我简单地介绍这两种方式的使用: 首先,要进行网络请求,我们要先给应用添加网络权限,有两种方式添加: 1.    打开AndroidManifest.

Android网络请求心路历程

HTTP请求&响应 既然说从入门级开始就说说Http请求包的结构.一次请求就是向目标服务器发送一串文本.什么样的文本?有下面结构的文本.HTTP请求包结构 例子: 1 2 3 4 5 6 7     POST /meme.php/home/user/login HTTP/1.1     Host: 114.215.86.90     Cache-Control: no-cache     Postman-Token: bd243d6b-da03-902f-0a2c-8e9377f6f6ed