一、Http协议

1、HTTP简介

大多数的Android应用程序都会使用HTTP协议来发送和接收网络数据,Android中主要提供了两种方式来进行HTTP操作,HttpURLConnection和HttpClient。所以首先介绍下Http协议。HTTP(HyperText Transfer Protocol,超文本传输协议) 是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。HTTP协议采用了请求/响应模型。通常,由HTTP客户端发起一个请求,建立一个到服务器指定端口(默认是80端口)的TCP连接,HTTP服务器则在那个端口监听客户端发送过来的请求。一旦收到请求,服务器(向客户端)发回一个状态行和响应消息,最后消息传送完毕时,可以关闭客户端和服务器端的连接。

2、HTTP消息

Http消息由从客户机到服务器的请求和从服务器到客户机的响应构成。这两种类型的消息均由一个起始行,一个或者多个头域,一个指示头域结束的空行和可选的消息体组成。HTTP的头域包括通用头,请求头,响应头和实体头四个部分。

请求消息格式如下:

请求行 - 通用信息头 - 请求头 - 实体头 - 消息主体

Android 网络(一)_第1张图片

如下所示:

Android 网络(一)_第2张图片

应答消息格式如下:

状态行 - 通用信息头 - 响应头 - 实体头 - 消息主体

Android 网络(一)_第3张图片

如下所示:

3、请求方法

注:Android HttpUrlConnection中只未提供Connect方法

方法

GET

请求指定url的数据,请求体为空(例如打开网页)

POST

请求指定url的数据,同时传递参数(在请求体中)

HEAD

类似于get请求,只不过返回的响应体为空,用于获取响应头

PUT

从客户端向服务器传送的数据取代指定的文档的内容

DELETE

请求服务器删除指定的页面

CONNECT

HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器

OPTIONS

允许客户端查看服务器的性能

TRACE

回显服务器收到的请求,主要用于测试或诊断。

4、状态码详解(Status Code)

状态码是一个用于标识服务器响应结果的代码,由3位数字表示。状态码的第一个数字定义响应的类别,后两个数字没有分类的作用。(状态码后面会跟随一段用于简要描述状态码信息的文本)

状态码类型:

类型

类型描述

1xx

信息响应类,表示接收到请求并且继续处理

2xx

处理成功响应类,表示动作被成功接收、理解和接受

3xx

重定向响应类,为了完成指定的动作,必须接受进一步处理

4xx

客户端错误,客户请求包含语法错误或者是不能正确执行

5xx

服务端错误,服务器不能正确执行一个正确的请求

常见状态码详解:

状态码

描述

200 OK

请求成功(其后是对GET和POST请求的应答文档)

301 Moved Permanently

所请求的页面已经转移至新的url

304 Not Modified

服务器端的数据在If-modified-since后未发生修改

400 Bad Request

服务器未能理解请求

401 Unauthorized

被请求的页面需要用户名和密码

404 Not Found

服务器无法找到被请求的页面

408 Request Timeout

请求超出了服务器的等待时间

500 Internal Server Error

请求未完成。服务器遇到不可预知的情况

501 Not Implemented

请求未完成。服务器不支持所请求的功能

5、头域详解

  • 通用头域

    通用头域包含请求和响应消息都支持的头域,通用头域包含Cache-Control、Connection、Date、Pragma、Transfer-Encoding、Upgrade、Via.
    1)Cache-Control:Cache-Control指定请求和响应遵循的缓存机制。请求时的缓存指令包括no-cache、no-store、max-age、max-stale、min-fresh、only-if-cached,响应消息中的指令包括public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age。
    2)Date头域:Date头域表示消息发送的时间,如Date:Mon,31Dec200104:25:57GMT

  • 请求头域

    请求头域中包含请求消息特有的头域信息,如Host、Range、User-Agent等

    1) Host:Host头域指定请求资源的Intenet主机和端口号;

    2)Range:Range头域可以请求实体的一个或者多个子范围,如bytes=500-600,601-9993);

    3)User-Agent:User-Agent头域的内容包含发出请求的用户信息

  • 响应头域

    响应头域中包含响应消息中特有的头域信息,如Location、Server等

  • 1)Location:Location头域用于重定向接收者到一个新URI地址;

    2)Server:Server头域包含处理请求的原始服务器的软件信息;

  • 实体头域

    请求消息和响应消息都可以包含实体信息,实体信息一般由实体头域和实体组成。实体头域包含关于实体的原信息,实体头包括Allow、Content-Base、Content-Encoding、Content-Language、Content-Length、Content-Location、Content-MD5、Content-Range、Content-Type、Etag、Expires、Last-Modified、extension-header;

  • 1)Content-Type:Content-Type实体头用于向接收方指示实体的介质类型,指定HEAD方法送到接收方的实体介质类型,或GET方法发送的请求介质类型;

    2)Content-Range:Content-Range实体头用于指定整个实体中的一部分的插入位置,他也指示了整个实体的长度。主要用于对范围请求的响应或对一系列范围的重叠请求。
    一般格式:Content-Range:bytes-unitSPfirst-byte-pos-last-byte-pos/entity-legth
    如:Content-Range:bytes0-499/1234;

    3)Last-modified:Last-modified实体头指定服务器上保存内容的最后修订时间

二、HttpClient & HttpURLConnection

1、HttpClient VS HttpURLConnection

HttpClient和HttpURLConnection是Android中提供的两种进行HTTP操作的方式,这两种方式都支持HTTPS协议、以流的形式进行上传和下载、配置超时时间、IPv6、以及连接池等功能。

DefaultHttpClient和AndroidHttpClient都是HttpClient的具体实现类,都拥有众多的API,而且实现比较稳定,bug数量也很少。但同时也由于HttpClient的API数量过多,使得很难在不破坏兼容性的情况下对它进行升级和扩展,所以目前Android团队在提升和优化HttpClient方面的工作态度并不积极;

而HttpURLConnection是一种多用途、轻量极的HTTP客户端,使用它来进行HTTP操作可以适用于大多数的应用程序,同时其升级与维护也相对比较简单。但在Android 2.3版本之前,HttpURLConnection一直存在着一些令人厌烦的bug。比如说对一个可读的InputStream调用close()方法时,就有可能会导致连接池失效。通常的解决办法就是直接禁用掉连接池的功能。

注意:Google建议Android2.3及以上版本的应用使用HttpURLConnection,而Android2.3以下版本的应用使用HttpClient。原因如下:

在Android 2.2版本之前,HttpClient拥有较少的bug,因此使用它是最好的选择。
而在Android 2.3版本及以后,HttpURLConnection则是最佳的选择。它的API简单,体积较小,因而非常适用于Android项目。压缩和缓存机制可以有效地减少网络访问的流量,在提升速度和省电方面也起到了较大的作用。同时,Google Android团队也在积极对该方式进行维护和升级。

2、HttpURLConnection的使用

/***采用HttpURLConnection进行网络请求的工具类*/publicclassAsyncNetworkUtil{privatestaticStringTAG="AsyncNetworkUtil";/***发送一个post请求*@paramurl:请求的地址*@paramcontent:post请求参数*@return:返回服务器响应信息*/publicstaticStringpost(Stringurl,Stringcontent){HttpURLConnectionconn=null;Stringresponse=null;try{//创建一个URL对象URLmURL=newURL(url);//调用URL的openConnection()方法,获取HttpURLConnection对象conn=(HttpURLConnection)mURL.openConnection();conn.setRequestMethod("POST");//设置请求方法为postconn.setReadTimeout(5000);//设置读取超时为5秒conn.setConnectTimeout(10000);//设置连接网络超时为10秒conn.setUseCaches(false);//设置不使用缓存conn.setDoOutput(true);//设置此方法,允许向服务器输出内容//post请求的参数Stringdata=content;//获得一个输出流,向服务器写数据,默认情况下,系统不允许向服务器输出内容OutputStreamout=conn.getOutputStream();out.write(data.getBytes());out.flush();out.close();intresponseCode=conn.getResponseCode();//调用此方法就不必再使用conn.connect()方法if(responseCode!=-1){InputStreamis=conn.getInputStream();response=getStringFromInputStream(is);}else{response="Novalidresponsecode";}}catch(Exceptione){e.printStackTrace();}finally{if(conn!=null){conn.disconnect();//关闭连接}}returnresponse;}/***发送一个get请求*@paramurl:请求的地址*@return:响应信息*/publicstaticStringget(Stringurl){HttpURLConnectionconn=null;try{//利用stringurl构建URL对象URLmURL=newURL(url);conn=(HttpURLConnection)mURL.openConnection();conn.setRequestMethod("GET");conn.setReadTimeout(5000);conn.setConnectTimeout(10000);conn.connect();intresponseCode=conn.getResponseCode();if(responseCode==200){InputStreamis=conn.getInputStream();Stringresponse=getStringFromInputStream(is);returnresponse;}elseif((responseCode+"")!=null&&(responseCode+"").length()!=0){returnresponseCode+"";}else{thrownewNetworkErrorException("responsestatusis"+responseCode);}}catch(Exceptione){e.printStackTrace();}finally{if(conn!=null){conn.disconnect();}}returnnull;}/***从输入流中获取数据*@paramis*@return*@throwsIOException*/privatestaticStringgetStringFromInputStream(InputStreamis)throwsIOException{ByteArrayOutputStreamos=newByteArrayOutputStream();//模板代码必须熟练byte[]buffer=newbyte[1024];intlen=-1;while((len=is.read(buffer))!=-1){os.write(buffer,0,len);}is.close();Stringstate=os.toString();//把流中的数据转换成字符串,采用的编码是utf-8(模拟器默认编码)os.close();returnstate;}}

三、Android网络操作一般流程

  1. 开启网络权限

  2. <uses-permissionandroid:name="android.permission.INTERNET"/><uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/>
  3. 检查设备的网络连接状况

  4. /***这是一个工具类,用于检测网络连接状况*/publicclassNetworkConnectivityUtil{privatestaticStringTAG="NetworkConnectivityUtil";//LogTagprivatestaticConnectivityManagerconnMgr;//网络连接管理器对象publicNetworkConnectivityUtil(Contextctx){connMgr=(ConnectivityManager)ctx.getSystemService(ctx.CONNECTIVITY_SERVICE);}/***检查网络连接状况*@returntrue:网络连通*false:网络未连通*/publicbooleancheckNetwork(){NetworkInfonetworkInfo=connMgr.getActiveNetworkInfo();returnnetworkInfo.isConnected()?true:false;}/***检查WIFI连接状况*@returntrue:网络连通*false:网络未连通*/publicbooleancheckWifi(){NetworkInfowifiInfo=connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);returnwifiInfo.isConnected()?true:false;}/***检查手机网络连接状况*@returntrue:网络连通*false:网络未连通*/publicbooleancheckMobile(){NetworkInfomobileInfo=connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);returnmobileInfo.isConnected()?true:false;}}
  5. 在工作线程中进行网络操作

  6. /***通过一个异步任务AsyncTask进行网络操作*/newAsyncTask<String,Void,String>(){@OverrideprotectedStringdoInBackground(String...params){//NetworkUtil.get即上面HttpURLConnection中的方法returnNetworkUtil.get(params[0]);}@OverrideprotectedvoidonPostExecute(Strings){editText.setText(s.substring(0,100));}}.execute(url);

更多相关文章

  1. 教你如何开关Android的APN网络
  2. 在android中显示网络图片及查看页面源代码
  3. Android网络收音机项目
  4. 2010-03-02 传智播客—Android(四)数据存储之五网络
  5. adb网络调试
  6. Android判断网络是否打开,并打开设置网络界面
  7. Android studio 通过以servlet搭建的服务器访问 PC端 mysql数据

随机推荐

  1. R语言包的安装
  2. 内存管理思想
  3. ESXI(VSphere)主机补丁离线升级(多图)
  4. 对接海康AI Cloud智能应用平台
  5. kubesphere中Metrics Server故障排查
  6. 文件内容差异对比
  7. Graylog 日志系统
  8. 标题test123
  9. Vscode的下载安装和必备插件的使用与Mark
  10. 程序员找不到女朋友?利用 Python 爬虫帮你