写在前面:个人总结,不一定全对,如有错误,请指出。
一、常用类
HTTP 是Internet 中广泛使用的协议,几乎所有的语言都会不同程度的支持HTTP,在Android SDK 中可以采用多种方式通过 HTTP 协议访问网络资源 。而Android中主要提供了两种方式来进行HTTP操作,
HttpURLConnection和HttpClient。这两种方式都支持HTTPS协议、以流的形式进行上传和下载、配置超时时间、
IPv6、以及连接池等功能。
HttpClient是个很不错的开源框架,封装了访问http的请求头,参数,内容体,响应等等,
HttpURLConnection是java的标准类,什么都没封装,用起来太原始,不方便,比如重访问的自定义,以及一些高级功能等。
android 2.2 之前尽量用HttpClient ,因为在Android 2.2版本之前,HttpURLConnection一直存在着一些令人厌烦的bug。但是后来高级版本的Android已经将bug修复,
并且做了一些进一步优化的工作。
1、HTTP是基于传输层的TCP协议,而TCP是一个端到端的面向连接的协议。所谓的端到端可以理解为进程到进程之间的通信。
所以HTTP在开始传输之前,首先需要建立TCP连接,而TCP连接的过程需要所谓的“三次握手”。
2、建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,
后边是MIME信息包括请求修饰符、客户机信息和可能的内容。
3、服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,
后边是MIME信息包括服务器信息、实体信息和可能的内容。
4、客户端接收服务器所返回的信息,然后对数据进行处理,显示到UI 上,然后客户机与服务器断开连接。
HTTP的请求内容
一个完整的HTTP请求包含:
1.一个请求行(GET /aa/index.html HTTP/1.0)
2.若干个请求头(告诉服务器客户端的一些信息)
3.实体内容(请求的时候需要向服务器传递的内容)。
三、HttpURLConnection 简介
3.1 继承结构
java.lang.Object
↳ java.net.URLConnection
↳ java.net.HttpURLConnection
对于HTTP的URLConnection(RFC 2616:RFC 2616定义了今天普遍使用的一个版本——HTTP 1.1)用于通过网络发送和接收数据。
数据可以是任何类型和长度。这个类可以用来发送和接收数据流的数据,其长度是事先不知道的。
3.2 类的使用模式
1、获得一个新的HttpURLConnection对象通过调用 URL.openConnection()
2、准备请求,这个请求的主要部分就是URL,请求头还可以包括
Accept:用于告诉服务器,客户机支持的数据类型(值为:text/html(文本),image(图片),/*/(任何类型)
Accept-Charset:客户机采用的编码
Accept-Encoding:客户机支持的压缩格式
Accept-Language:客户机的语言环境,不同国家访问的内容也是不同的,就是通过这个头实现的,用于实现国际化
Host:告诉服务器,想访问的主机名
If-Modified-Since:客户机将这个头信息发送给服务端,服务端进行比对,告诉客户机是否去拿缓存,和服务器端返回的Last-Modified值是相等的
If-None-Match:客户机将这个头信息发送给服务端,服务端进行比对,告诉客户机是否去拿缓存,和服务器端返回的Etag值是相等的
Referer:客户机告诉服务器,他是从哪个资源来访问服务器的(防盗链),通过检查该头是否是从本网站点击过来的,如不是的,就让他跳到本网站的首页来
User-Agen::客户机告诉服务器,客户机的软件环境
Cookie:客户机通过这个头向服务器带点数据
Connection:客户机的连接状态(close:关闭连接 Keep-Alive:不会断开连接)
3、如果有上传实体请求(post 方式),实例必现setDoOutput(true) ,上传实体数据通过getOutputStream()返回的流。 (请求方式为get方式,则可以再请求的URL地址后以?的形式带上交给服务器的数据,多个数据之间以&进行分割,同时在URL地址后附带的参数是有限制的,其数据容量通常不能超过1k,若请求方式为post方式,则可以再请求的实体内容中向服务器发送数据,post方式的特点:传送的数据无限制.)
4、读取响应信息。可通过getInputStream() 获取的流。 如果没有实体,返回的是一个空流
用于描述服务器的基本信息,以及数据的描述,服务器通过这些数据的描述信息,可以通知客户端如何处理等一会它会送的数据
Location:这个头配合302状态码使用,用于告诉用户找谁 。 请求重定向,判断浏览器的地址栏的地址是否发生变化,实例是用户登录
Server:服务器通过这个头,告诉浏览器的类型
Content-Encoding:服务器通过这个头,数据的压缩格式,收费是靠数据出口量算的, 所以为了省钱和效率高,要进行数据压缩,jdk中的GZIPOutputStream类,压缩类流,包装流和底层流,最好将包装流关了或者刷新,数据写入到底层流中去,
Content-Length:服务器会送的数据的长度
Content-Type:服务器会送数据的类型,response.getOutputStream().write();服务器会送数据都是二进制,通过这个头,可以告诉浏览器这个二进制是什么类型,在服务器的目录下的web.xml中查看各个数据类型的respose.setHeader("content-type","")的写法.
Refresh:告诉浏览器隔多长时间刷新一次,response.setHeader("refresh","3;url=""")控制浏览器隔三秒跳到指定的网页上
Content-Disposition:告诉浏览器以下载的方式打开文件
Transfer-Encoding:告诉浏览器数据的传送格式
Last-Modified:服务端文件的最后修改时间,这个值返回给客户端,客户机第二次访问服务器时带来的If-Modified-Since的值和服务器的值一样,就拿缓存给客户,实时更新,
ETag:缓存相关的头,服务器根据数据的内容生产一个字符串,客户机第二次访问服务器时带来的If-None-Match的值和服务器的值一样,就拿缓存给客户,实时更新,
Expires:高速浏览器,把会送的资源缓存多少时间,-1或0,则是不缓存的
Pragma:no-cache
Cache-Control:no-cache
Date:控制浏览器不要缓存数据,当数据不发生改变时,就要缓存,当实时性要求很高的数据不能缓存.
5、断开,一但响应已经被读取,HttpURLConnection 将会被关闭,通过调用disconnect();断开连接,释放资源。
一个简单的例子:
URL url = new URL("http://www.android.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
readStream(in);
finally {
urlConnection.disconnect();
}
}
3.3 与HTTPS的安全通信
通过一个为 “https” 的URL 调用 openConnection() ,返回一个HttpsURLConnection 实例。具体的,请参见 HttpsURLConnection 相关API。
3.4 响应处理
如果HTTP响应表明发生了一个错误,getinputstream()将抛出一个异常。使用geterrorstream()读取错误响应。错误响应头可以用getheaderfields()正常方式读,
3.5 post 数据
将数据上传到WEB 服务器,必需为连接配置setDoOutput(true),为了获得更好的性能,如果上传的数据长度是预先知道的,应该调用 setFixedLengthStreamingMode(int)
如果不知道的话,调用setChunkedStreamingMode(int)。否则,HttpURLConnection 将会被迫在内存中缓冲完整的请求体,浪费(或可能耗尽)堆内存和增加延迟。
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
urlConnection.setDoOutput(true);
urlConnection.setChunkedStreamingMode(0); //设置长度未可知
//urlConnection.setFixedLengthStreamingMode(38); //如果上传的内容长度已知
OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
writeStream(out);
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
readStream(in);
finally {
urlConnection.disconnect();
}
}
补充说明:HttpURLConnection的输出流是首先在本地内存进行缓存,然后再一次性输出的到服务器端。如果长度过大的话,可能造成内存溢出。
setChunkedStreamingMode(int)
//通俗点讲就是不知道要上传的body(实体,就是写入流的数据参照) 部分的长度,而默认是缓存完毕才一次性输出,如果实体过大,可能造成内存异常。而这个方法的作用
就是设定一个固定大小的缓存块,当缓存数据达到这个块的大小后,就输出。每个块会复制必需有的头信息。
如果设置的块太大的话,有可能浪费内存。如果设置的块长度太小,就会增加发送头信息的字节数。 所以一般设置为 0 ,来获取系统默认的值。
setFixedLengthStreamingMode(int)
//通俗点将就是设置 请求 body 的具体长度,这样也不会去缓存全部才输出。而是采用流式的输出。
3.6 性能
这个类返回的输出输入流并没有缓冲区功能,大多数要调用者自己去封装为BufferedInputStream 或 BufferedOutputStream。当然,如果数据过大,可以省略缓冲。
当将大量的数据传送到服务器,使用数据流来限制内存中的数据量,除非你想缓存所有的数据在内存中。
为了减少延迟,这个类可以重用多个请求/响应对相同的底层套接字 (http1.1),基于这样,http连接能够保存较长的时间,调用disconnect() 会返回socket 到 连接套接字池。
当然,如果你设置http.keepAlive 属性为false,这种情况就不会出现了。http.maxConnections 可以控制有多少空闲连接。
默认情况下,HttpURLConnection 是使用 gzip 压缩的(android 版本大于2.2)。所以你不能用getContentLength() 方法来返回将要传输的的数据长度,你只能用getInputStream() 获取流后,一直read()到 返回值为-1的时候,才能确定完整的长度。所以,你要使用getContentLength() 来获取将要获取数据的长度时(断点续传常用),
要调用以下方法关闭 gzip。
urlConnection.setRequestProperty("Accept-Encoding", "identity");
3.7 处理网络标志
有些wi-fi 是有网络登录页,这样的登录页其实就是使用重定向实现的。你可以使用getURL()来判断你目前的连接是否被重定向了。例如:
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
if (!url.getHost().equals(urlConnection.getURL().getHost())) {
// we were redirected! Kick the user out to the browser to sign on?
...
} finally {
urlConnection.disconnect();
}
}
3.8 HTTP认证
HttpURLConnection 支持 HTTP basic authentication,
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
});
}
basic authentication(HTTP1.0提出的认证方法)说明:
基本认证是一种用来允许Web浏览器或其他客户端程序在请求时提供用户名和口令形式的身份凭证的一种登录验证方式。
把 "用户名+冒号+密码"用BASE64算法加密后的字符串放在http request 中的header Authorization中发送给服务端。
客户端对于每一个realm,通过提供用户名和密码来进行认证的方式。
包含密码的明文传递。
当浏览器访问使用基本认证的网站的时候, 浏览器会提示你输入用户名和密码,如下图:
假如用户名密码错误的话,服务器会返回401,可参加博客:http://blog.youkuaiyun.com/kiwi_coder/article/details/28677651
3.9 带有Cookies 的会话
建立和维护客户和服务器之间潜在的长期会话,HttpURLConnection 包含了一个扩展的cookie 管理。广泛使用,cookiemanager cookiehandler cookie管理:
CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);
默认情况下 CookieManager 保存所有的cookies
在内存中,当虚拟机退出后,将清楚这些cookies 。
实现CookieStore 定义一个自定义Cookie存储。
HttpCookie cookie = new HttpCookie("lang", "fr");
cookie.setDomain("twitter.com");
cookie.setPath("/");
cookie.setVersion(0);
cookieManager.getCookieStore().add(new URI("http://twitter.com/"), cookie);
3.10 http 请求方式
HttpURLConnection 默认使用GET 方式,如果调用setDoOutput(true),将会使用POST 方式,其他请求方式(OPTIONS
,HEAD
,PUT
, DELETE
and TRACE
)请调用setRequestMethod(String)
3.11 代理
默认情况下,直接连接到源服务器,它还可以通过HTTP或SOCKS代理。使用代理,使用URL.OpenConnection(代理)创建连接时。
3.12 IP V6 支持
默认支持IP V6,与IPv4和IPv6地址的主机,它将尝试连接到每个主机的地址,直到建立连接。
3.13响应缓存
android4.0之后,加入了缓存机制,请查看android.net.http.HttpResponseCache 类 如何实现缓存在你应用
3.14 避免在早期版本中的错误
在android2.2 之前,这个类不友好,有很多bug,比如说对一个可读的InputStream调用close()方法时,就有可能会导致连接池失效了。那么我们通常的解决办法就是直接禁用掉连接池的功能:
private void disableConnectionReuseIfNecessary() {
// Work around pre-Froyo bugs in HTTP connection reuse.
if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) {
System.setProperty("http.keepAlive", "false");
}}
你的每个HttpURLConnection实例都可以作为一个请求/响应对。这个类的实例是线程不安全的。
Summary
Constants
int HTTP_ACCEPTED Numeric status code, 202: Accepted
int HTTP_BAD_GATEWAY Numeric status code, 502: Bad Gateway
int HTTP_BAD_METHOD Numeric status code, 405: Bad Method
int HTTP_BAD_REQUEST Numeric status code, 400: Bad Request
int HTTP_CLIENT_TIMEOUT Numeric status code, 408: Client Timeout
int HTTP_CONFLICT Numeric status code, 409: Conflict
int HTTP_CREATED Numeric status code, 201: Created
int HTTP_ENTITY_TOO_LARGE Numeric status code, 413: Entity too large
int HTTP_FORBIDDEN Numeric status code, 403: Forbidden
int HTTP_GATEWAY_TIMEOUT Numeric status code, 504: Gateway timeout
int HTTP_GONE Numeric status code, 410: Gone
int HTTP_INTERNAL_ERROR Numeric status code, 500: Internal error
int HTTP_LENGTH_REQUIRED Numeric status code, 411: Length required
int HTTP_MOVED_PERM Numeric status code, 301 Moved permanently
int HTTP_MOVED_TEMP Numeric status code, 302: Moved temporarily
int HTTP_MULT_CHOICE Numeric status code, 300: Multiple choices
int HTTP_NOT_ACCEPTABLE Numeric status code, 406: Not acceptable
int HTTP_NOT_AUTHORITATIVE Numeric status code, 203: Not authoritative
int HTTP_NOT_FOUND Numeric status code, 404: Not found
int HTTP_NOT_IMPLEMENTED Numeric status code, 501: Not implemented
int HTTP_NOT_MODIFIED Numeric status code, 304: Not modified
int HTTP_NO_CONTENT Numeric status code, 204: No content
int HTTP_OK Numeric status code, 200: OK
int HTTP_PARTIAL Numeric status code, 206: Partial
int HTTP_PAYMENT_REQUIRED Numeric status code, 402: Payment required
int HTTP_PRECON_FAILED Numeric status code, 412: Precondition failed
int HTTP_PROXY_AUTH Numeric status code, 407: Proxy authentication required
int HTTP_REQ_TOO_LONG Numeric status code, 414: Request too long
int HTTP_RESET Numeric status code, 205: Reset
int HTTP_SEE_OTHER Numeric status code, 303: See other
int HTTP_SERVER_ERROR This constant was deprecated in API level 1. Use HTTP_INTERNAL_ERROR instead.
int HTTP_UNAUTHORIZED Numeric status code, 401: Unauthorized
int HTTP_UNAVAILABLE Numeric status code, 503: Unavailable
int HTTP_UNSUPPORTED_TYPE Numeric status code, 415: Unsupported type
int HTTP_USE_PROXY Numeric status code, 305: Use proxy.
int HTTP_VERSION Numeric status code, 505: Version not supported
Fields
protected int chunkLength If the HTTP chunked encoding is enabled this parameter defines the chunk-length.
protected int fixedContentLength The byte count in the request body if it is both known and streamed; and -1 otherwise.
protected long fixedContentLengthLong The byte count in the request body if it is both known and streamed; and -1 otherwise.
protected boolean instanceFollowRedirects Flag to define whether the protocol will automatically follow redirects or not.
protected String method The HTTP request method of this HttpURLConnection.
protected int responseCode The status code of the response obtained from the HTTP request.
protected String responseMessage The HTTP response message which corresponds to the response code.
[Expand]
Inherited Fields
From class java.net.URLConnection
Protected Constructors
HttpURLConnection(URL url)
Constructs a new HttpURLConnection instance pointing to the resource specified by the url.
Public Methods
abstract void disconnect()
Releases this connection so that its resources may be either reused or closed.
String getContentEncoding()
Returns the encoding used to transmit the response body over the network.
InputStream getErrorStream()
Returns an input stream from the server in the case of an error such as the requested file has not been found on the remote server.
static boolean getFollowRedirects()
Returns the value of followRedirects which indicates if this connection follows a different URL redirected by the server.
long getHeaderFieldDate(String field, long defaultValue)
Returns the date value in milliseconds since 01.01.1970, 00:00h corresponding to the header field field.
boolean getInstanceFollowRedirects()
Returns whether this connection follows redirects.
Permission getPermission()
Returns the permission object (in this case SocketPermission) with the host and the port number as the target name and "resolve, connect" as the action list.
String getRequestMethod()
Returns the request method which will be used to make the request to the remote HTTP server.
int getResponseCode()
Returns the response code returned by the remote HTTP server.
String getResponseMessage()
Returns the response message returned by the remote HTTP server.
void setChunkedStreamingMode(int chunkLength)
Stream a request body whose length is not known in advance.
void setFixedLengthStreamingMode(int contentLength)
Equivalent to setFixedLengthStreamingMode((long) contentLength), but available on earlier versions of Android and limited to 2 GiB.
void setFixedLengthStreamingMode(long contentLength)
Configures this connection to stream the request body with the known fixed byte count of contentLength.
static void setFollowRedirects(boolean auto)
Sets the flag of whether this connection will follow redirects returned by the remote server.
void setInstanceFollowRedirects(boolean followRedirects)
Sets whether this connection follows redirects.
void setRequestMethod(String method)
Sets the request command which will be sent to the remote HTTP server.
abstract boolean usingProxy()
Returns whether this connection uses a proxy server or not.
四、HttpClient 简介
4.1 类概述
一个HTTP客户端接口。HTTP客户端封装各种对象需要执行HTTP请求处理、cookie认证,连接管理,等功能。HTTP客户端的线程安全性取决于特定的客户端的实现和配置。
4.2 通用步骤
1)、创建 HttpGet 或 HttpClient 对象,将要请求的URL 通过构造方法传入HttpGet 或 HttpClient 对象
String url = “http://www.android.com/”;
HttpGet request = new HttpGet(url);
2)、使用DefaultHttpClient 类的execute 方法 发送HTTP GET 活HTTP POST 请求,并返回 HttpResponse 对象
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(request);
3)、 通过httpResponse 接口的getEntity 方法返回响应信息,并进行相应的处理
if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String data = EntityUtils.toString(response.getEntity());
}
4.3 HttpPost
java.lang.Object | ||||
↳ | org.apache.http.message.AbstractHttpMessage | |||
↳ | org.apache.http.client.methods.HttpRequestBase | |||
↳ | org.apache.http.client.methods.HttpEntityEnclosingRequestBase | |||
↳ | org.apache.http.client.methods.HttpPost |
仅有的公共方法 与常量
Summary
Constants
String METHOD_NAME
[Expand]
Inherited Fields
From class org.apache.http.message.AbstractHttpMessage
Public Constructors
HttpPost()
HttpPost(URI uri)
HttpPost(String uri)
Public Methods
String getMethod()
Returns the HTTP method this request uses, such as GET, PUT, POST, or other.
4.4 HttpGet
仅有的公共方法 与常量
Summary
Constants
String METHOD_NAME
[Expand]
Inherited Fields
From class org.apache.http.message.AbstractHttpMessage
Public Constructors
HttpGet()
HttpGet(URI uri)
HttpGet(String uri)
Public Methods
String getMethod()
Returns the HTTP method this request uses, such as GET, PUT, POST, or other.
http://xiaowei-qi-epro-com-cn.iteye.com/blog/1973295
http://blog.youkuaiyun.com/hguang_zjh/article/details/33743249
http://blog.youkuaiyun.com/jiangwei0910410003/article/details/22795873
http://write.blog.youkuaiyun.com/postedit
http://ferreousbox.iteye.com/blog/157728