Android中的HTTP通信
前言:近期在慕课网学习了慕课网课程Android中的HTTP通信,就自己总结了一下,其中参考了不少博文,感谢大家的分享。
文章内容包括:
1.HTTP简介
2.HTTP/1.0和HTTP/1.1之间的区别
3.HTTP的请求头、响应头和状态码
4.Android中的HttpUrlConnection
1.Http简介
Http(Hypertext transfer protocol)定义了浏览器怎么向万维网服务器发送万维网文档,以及服务器怎么将文档发送给服务器。从层次上看,http是面向应用层协议的,它是万维网能够可靠交换文档的基础。
http的工作流程
当用户点击一个链接(假设URL为http://www.tsinghua.edu.cn/chn/yxsz/index.html ),所发生的事件流程:
(1)浏览器分析连接所指向的页面的URL。
(2)浏览器向DNS请求解析www.tsinghua.edu.cn的IP地址。
(3)浏览器解析出服务器的IP地址。
(4)浏览器与服务器建立TCP连接。
(5)浏览器发出取文件指令:GET /chn/yxsz/index.html。
(5)服务器给出响应,将文件index.html发送给浏览器。
(6)释放TCP连接。
(7)浏览器显示index.html的所用信息。
Http的特点
(1)支持客服/服务器(C/S)模式
(2)简单快速,客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、POST、HEAD。每种方法规定了与服务器的连接不同,由于HTTP协议简单,使得HTTP服务器的程序规模更小、因而通信更快。
(3)HTTP是无连接的。无连接意味者HTTP每次只处理一个请求,服务器处理完处理完客户的请求,并且收到客户的应答后,即断开连接,可以节省传输时间。
(4)HTTP是无状态的。无状态意味者HTTP协议对于事务没有记忆能力,缺少状态表示后续处理需要前面的信息,则它必须重传。这可能使它没次连接传输的信息量增大,另一方面、服务器在不需要先前信息就表现的非常快,同时是服务器更容易支持大量的并发的HTTP请求。
PS:虽然HTTP是无连接的协议,但HTTP使用了面向连接的运输层协议TCP,因此保证了数据的可靠传输,HTTP不用考虑数据在传输过程中被丢弃了如何重传。
2.HTTP/1.0和HTTP/1.1之间的区别
HTTP/1.0的主要缺点是它使用非持续连接每请求一个文档需要两倍的RTT的开销。这时的协议如果一个主页有很多链接的对象(如图片),每个链接都需要建立新的TCP连接,那么每一次链接下载都会导致2×RTT的开销。
HTTP/1.1协议很好的解决了这个问题,它使用了持续连接,万维网服务器在发送响应后的一段时间内仍然保持着这个连接,是同一个客户可以和该服务器传送后续的HTTP请求报文和响应报文。
3.HTTP的请求头、响应头和状态码
请求头(进入简书的请求头,可以通过Firfox浏览器通过开发者选项打开网络查看(快捷键ctrl+shift+Q))。
GET http://www.jianshu.com/
Host: www.jianshu.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: https://www.google.com.hk
Cookie: (略)
Connection: keep-alive
If-None-Match: W/"b4e2a47d84be2df34bb1d5b79be9c040"
Cache-Control: max-age=0
下面说下具体的含义:
GET定义了请求的方法。同样的方法共有8种(下面会列出)。
Host:初始URL中的主机和端口。
User-Agent:浏览器类型,如果Servlet返回的内容与浏览器类型有关则该值非常有用。
Accept:浏览器可接受的MIME类型。
Accept-Charset:浏览器可接受的字符集。
Accept-Language:浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到。
Accept-Encoding:浏览器能够进行解码的数据编码方式,比如gzip。Servlet能够向支持gzip的浏览器返回经gzip编码的HTML页面。许多情形下这可以减少5到10倍的下载时间。
Referer:包含一个URL,用户从该URL代表的页面出发访问当前请求的页面。
Cookie:这是最重要的请求头信息之一,HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。
Connection:
表示是否需要持久连接。如果Servlet看到这里的值为“Keep- Alive”,或者看到请求使用的是HTTP 1.1(HTTP
1.1默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。要实现这一
点,Servlet需要在应答中发送一个Content-Length头,最简单的实现方法是:先把内容写入
ByteArrayOutputStream,然后在正式写出内容之前计算它的大小。
Cache-Control:If-None-Match:如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改。
Cache-Control:指定请求和响应遵循的缓存机制。
8中请求方法解释(摘自:http://itbilu.com/other/relate/EkwKysXIl.html)
GET
请求会显示请求指定的资源。一般来说GET方法应该只用于数据的读取,而不应当用于会产生副作用的非幂等的操作中。GET方法请求指定的页面信息,并返回响应主体,GET被认为是不安全的方法,因为GET方法会被网络蜘蛛等任意的访问。
HEAD
方法与GET方法一样,都是向服务器发出指定资源的请求。但是,服务器在响应HEAD
请求时不会回传资源的内容部分,即:响应主体。这样,我们可以不传输全部内容的情况下,就可以获取服务器的响应头信息。HEAD方法常被用于客户端查看服务器的性能。
POST
请求会向指定资源提交数据,请求服务器进行处理,如:表单数据提交、文件上传等,请求数据会被包含在请求体中。POST方法是非幂等的方法,因为这个请求可能会创建新的资源或/和修改现有资源。
PUT
请求会身向指定资源位置上传其最新内容,PUT方法是幂等的方法。通过该方法客户端可以将指定资源的最新数据传送给服务器取代指定的资源的内容。
DELETE
请求用于请求服务器删除所请求URI(统一资源标识符,Uniform Resource Identifier)所标识的资源。DELETE请求后指定资源会被删除,DELETE方法也是幂等
的。
CONNECT
该方法是HTTP/1.1协议预留的,能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接与非加密的HTTP代理服务器的通信。
OPTIONS
请求与HEAD类似,一般也是用于客户端查看服务器的性能。这个方法会请求服务器返回该资源所支持的所有HTTP请求方法,该方法会用''来代替资源名称,向服务器发送OPTIONS请求,可以测试服务器功能是否正常。JavaScript的XMLHttpRequest对象进行CORS跨域资源共享时,就是使用OPTIONS方法发送嗅探请求,以判断是否有对指定资源的访问权限。允许
*TRACE
请求服务器回显其收到的请求信息,该方法主要用于HTTP请求的测试或诊断。
*响应头(同样是在请求简书首页的响应头
Cache-Control: max-age=0, private, must-revalidate
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Date: Sun, 19 Jun 2016 15:29:41 GMT
Etag: W/"e9a43aabd740855cd3fe0097faf6180d"
Server: nginx
Set-Cookie: (略)
Vary: Accept-Encoding
X-Request-Id: ce26a795-7e99-4959-a498-45f689471d7f
X-Runtime: 0.596683
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 1; mode=block
Cache-Control指定请求和响应遵循的缓存机制。
Connection:表示是否需要持久连接。
Content-Encoding 文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档 的下载时间。
Content-
Type
表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。由于经常要设置
Content-Type,因此HttpServletResponse提供了一个专用的方法setContentTyep。
Date 当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。
Etag 请求变量的实体标签的当前值。
Server 服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置。
Set-Cookie 设置和页面关联的Cookie。
Vary 告诉下游代理是使用缓存响应还是从原始服务器请求
更为详细的请求头与响应头信息,请参考:HTTP Header 详解
*状态码
1XX :表示通知信息的,如请求收到了或正在处理。
2XX :表示成功,如接收或知道了。
3XX :表示重定向,如要完成还需采取进一步处理。
4XX :表示客户的差错,如请求中有错误的语法或不能完成。
5XX :表示服务器的差错,如服务器失效无法完成请求。
4.Android中的HttpUrlConnection
Android中的连接主要是通过HttpUrlConnection来完成的,下面将要从HttpUrlConnection使用、get和post传递参数、多线程下载三个方面来看HttpUrlClient的用法:
(1)HttpUrlConnection的使用格式:URL url = new URL("http://localhost:8080/TestHttpURLConnectionPro/index.jsp"); //将地址转换为URL
URLConnection rulConnection = url.openConnection(); // 此处的urlConnection对象实际上是根据URL的请求协议(此处是http)生成的URLConnection类的子类HttpURLConnection,故此处最好将其转化为HttpURLConnection类型的对象
HttpURLConnection httpUrlConnection = (HttpURLConnection) rulConnection;
设置HttpUrlClient的连接参数:// 设置是否向httpUrlConnection输出,因为这个是post请求,参数要放在。http正文内,因此需要设为true, 默认情况下是false;
httpUrlConnection.setDoOutput(true);
//设置是否从httpUrlConnection读入,默认情况下是true;
httpUrlConnection.setDoInput(true);
// Post 请求不能使用缓存
httpUrlConnection.setUseCaches(false);
// 设定传送的内容类型是可序列化的java对象
// (如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException)
httpUrlConnection.setRequestProperty("Content-type", "application/x-java-serialized-object");
// 设定请求的方法为"POST",默认是GET
httpUrlConnection.setRequestMethod("POST");
// 连接,从上述第2条中url.openConnection()至此的配置必须要在connect之前完成,
httpUrlConnection.connect();
对于HttpUrlConnection在代码中的具体用法,看下面都是一样的用法,看过就懂了。
(2)get和post方式传递参数
get方式
使用get方式传递参数关键在于URl,在代码中可以看出我们在url中附加了一些数据,实际上get方式就是在通过在url中附加数据来传递参数的,因此采用这种方式是很不安全的。private void doGet(){
try {
url = url + "?name=" + URLEncoder.encode(name,"utf-8") + "&age=" + age;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
URL httpUrl = new URL(url); //新建URL对象
HttpURLConnection conn = (HttpURLConnection) httpUrl.openConnection();//打开一个连接
conn.setRequestMethod("GET");//设置请求方法为GET
conn.setReadTimeout(5000);//设置从服务器读取数据的超时限制为5秒
BufferedReader reader = new BufferedReader(
new InputStreamReader(conn.getInputStream()));//获取服务器传递的数据输入流
String str;
StringBuffer sb = new StringBuffer(); //存储读取的数据
while((str = reader.readLine()) != null){//读取数据
sb.append(str);
}
System.out.println("result:"+sb.toString());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
POST方式
post传递参数的方式与get是不同的,它会将传递的数据写入到请求的正文中。private void doPost(){
try {
URL HttpUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) HttpUrl.openConnection();
conn.setRequestMethod("POST");
conn.setReadTimeout(5000);
OutputStream out = conn.getOutputStream(); //新建输出流对象
String content = "name="+name+"&age="+age;//传递对象
out.write(content.getBytes());//将传递对象转为字符流写入输出流中
//下面是对于服务器返回数据的处理
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuffer sb = new StringBuffer();
String str;
while((str=reader.readLine())!=null){
sb.append(str);
}
System.out.println(sb.toString());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
(3)多线程下载
public class DownLoad {
private Executor threadPool = Executors.newFixedThreadPool(3);
private Handler handler;
public DownLoad(Handler handler){
this.handler = handler;
}
static class DownLoadRunnable implements Runnable {
private String url;
private String fileName;
private long start;
private long end;
private Handler handler;
public DownLoadRunnable(String url,String fileName,long start,long end,Handler handler){
this.url = url;
this.fileName = fileName;
this.start = start;
this.end = end;
this.handler = handler;
}
@Override
public void run() {
try {
URL httpUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) httpUrl.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Range","bytes="+start+"-"+end);
conn.setReadTimeout(5000);
RandomAccessFile access = new RandomAccessFile(new File(fileName),"rwd");
access.seek(start);
InputStream in = conn.getInputStream();
byte[] b = new byte[1024*4];
int len=0;
while((len=in.read(b))!=-1){
access.write(b,0,len);
}
if (access!=null){
access.close();
}
if (in!=null){
in.close();
}
Message msg = new Message();
msg.what = 1;
handler.sendMessage(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void loadFile(String url) {
try {
URL httpUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) httpUrl.openConnection();
conn.setRequestMethod("GET");
conn.setReadTimeout(5000);
int count = conn.getContentLength();
int block = count / 3;
String fileName = getFileName(url);
File parent = Environment.getExternalStorageDirectory();
File download = new File(parent,fileName);
for (int i=0;i<3;i++){
long start = i*block;
long end = (i+1)*block-1;
if (i==2){
end = count;
}
DownLoadRunnable runnable = new DownLoadRunnable(url,download.getAbsolutePath(),start,end,handler);
threadPool.execute(runnable);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public String getFileName(String url){
return url.substring(url.lastIndexOf("/")+1);
}
}
参考:
(1)慕课网课程Android中的HTTP通信
(2)HTTP请求方法:GET、HEAD、POST、PUT、DELETE、CONNECT、OPTIONS、TRACE
(3)HTTP响应头信息和请求头信息详解
(4)HTTP Header 详解
Android中的HTTP通信的更多相关文章
- Android中线程间通信原理分析:Looper,MessageQueue,Handler
自问自答的两个问题 在我们去讨论Handler,Looper,MessageQueue的关系之前,我们需要先问两个问题: 1.这一套东西搞出来是为了解决什么问题呢? 2.如果让我们来解决这个问题该怎么 ...
- Android中的常见通信机制和Linux中的通信机制
Handler Handler是Android系统中的一种消息传递机制,起作用是应对多线程场景.将A进程的消息传递给B线程,实现异步消息处理.很多情况是将工作线程中需要更新UI的操作消息传递给UI主线 ...
- EventBus在Android中的简单使用
EventBus是一个方便与Android中各组件通信的开源框架,开源地址;https://github.com/greenrobot/EventBus.EventBus功能非常强大 ,今天在做一个功 ...
- android中四大组件之间相互通信
好久没有写有关android有关的博客了,今天主要来谈一谈android中四大组件.首先,接触android的人,都应该知道android中有四大组件,activity,service,broadca ...
- Android中实现java与PHP服务器(基于新浪云免费云平台)http通信详解
Android中实现java与PHP服务器(基于新浪云免费云平台)http通信详解 (本文转自: http://blog.csdn.net/yinhaide/article/details/44756 ...
- (六)Android中Service通信
一.启动Service并传递参数 传递参数时只需在startService启动的Intent中传入数据便可,接收参数时可在onStartCommand函数中通过读取第一个参数Intent的内容来实现 ...
- 从Android中Activity之间的通信说开来[转]
http://www.cnblogs.com/virusswb/archive/2011/08/02/2124824.html 引言 最近两个星期在研究android的应用开发,学习了android应 ...
- Android中的跨进程通信方法实例及特点分析(二):ContentProvider
1.ContentProvider简单介绍 在Android中有些数据(如通讯录.音频.视频文件等)是要供非常多应用程序使用的.为了更好地对外提供数据.Android系统给我们提供了Content P ...
- Android中使用开源框架EventBus3.0实现Fragment之间的通信交互
1.概述 在之前的博文中简单介绍过如何实现fragment之间的信息交互:<Android中Fragment与Activity之间的交互(两种实现方式)>,今天继续给大家介绍一种可以实现此 ...
随机推荐
- Python的安装和详细配置
Python是一种面向对象.解释型计算机程序设计语言.被认为是比较好的胶水语言.至于其他的,你可以去百度一下.本文仅介绍python的安装和配置,供刚入门的朋友快速搭建自己的学习和开发环境.本人欢迎大 ...
- Kooboo CMS - @Html.FrontHtml().HtmlTitle() 详解
首先我们找到这个类. 这个类有如下的方法: #region Title & meta [Obsolete("Use HtmlTitle")] public IHtmlStr ...
- JConsole远程连接配置
JConsole远程连接还是有一点坑的.这里记录一下配置过程,好记性不如烂笔头. 1.在远程机的tomcat的catalina.sh中加入配置: JAVA_OPTS="$JAVA_OPTS ...
- Unity实现滑页嵌套(解决ScrollRect嵌套冲突问题)
简介 由于项目需要+有网友咨询,所以做了个横向滑页+某一横向滑页中有竖向滑页的demo,实现有点绕弯子,但基本功能还是比较完善,发上来共享一下. 效果 思路 第一步的思路是自己判断触屏拖动位置,然后控 ...
- NHibernate生成实体类、xml映射文件
最近工作电脑装完win10后,之前使用的codeSmith安装不了,索性自己写一个. 界面比较简单,如下图: 第一行为Oracle数据库的连接字符串.连接成功后,填充表到第4行的下拉列表中. 第二行为 ...
- ASP.NET Core开发-如何配置Kestrel 网址Urls
ASP.NET Core中如何配置Kestrel Urls呢,大家可能都知道使用UseUrls() 方法来配置. 今天给介绍全面的ASP.NET Core 配置 Urls,使用多种方式配置Urls. ...
- 装饰模式 - Decorator 和 外观模式 - Facade
装饰模式 Decorator,不改变接口但动态给对象加入责任,所需功能按顺序串联起来控制,比生成子类灵活. 外观模式 Facade,让接口更简单.为子系统中的一组接口提供一个一致的界面. 参考:
- eclipse报错:Failed to load the JNI shared library
Eclipse运行时提示“Failed to load the JNI shared library /Java/jre6/bin/client/jvm.dll”的一个解决方案 因为 Eclipse ...
- struts2的action是多例,servlet是单例
struts2中action是多例的,即一个session产生一个action如果是单例的话,若出现两个用户都修改一个对象的属性值,则会因为用户修改时间不同,两个用户访问得到的 属性不一样,操作得出的 ...
- Guava学习-缓存
Guava的缓存是本地缓存,所以我觉得在使用场景上适合那种并非是高一致性的场景中,而且他的实现和ConcurrentHashMap很类似.但是毕竟是缓存嘛,肯定有自动清除的功能.外加一些什么清除策略等 ...