Android网络编程

一、网络的基本知识:

  • 计算机网络:是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
  • 计算机网络体系结构:Android网络编程_第1张图片

1、HTTP协议:

超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的 WWW(万维网) 文件都必须遵守这个标准。设计 HTTP 最初的目的是为了提供一种发布和接收 HTML 页面的方法。

HTTP协议的主要特点:

  • 支持C/S(客户/服务器)模式。
  • 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST,每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
  • 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
  • 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
  • 无状态:HTTP协议是无状态协议,无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

HTTP的消息报头:

消息报头分为通用报头、请求报头、响应报头、实体报头等。消息头由键值对组成,每行一对,关键字和值用英文冒号“:”分隔。

  • 通用报头:(既可以出现在请求报头,也可以出现在响应报头中)
    Date:表示消息产生的日期和时间
    Connection:允许发送指定连接的选项,例如指定连接是连续的,或者指定“close”选项,通知服务器,在响应完成后,关闭连接
    Cache-Control:用于指定缓存指令,缓存指令是单向的(响应中出现的缓存指令在请求中未必会出现),且是独立的(一个消息的缓存指令不会影响另一个消息处理的缓存机制)
  • 请求报头
    请求报头通知服务器关于客户端求求的信息,典型的请求头有:
    Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机
    User-Agent:发送请求的浏览器类型、操作系统等信息
    Accept:客户端可识别的内容类型列表,用于指定客户端接收那些类型的信息
    Accept-Encoding:客户端可识别的数据编码
    Accept-Language:表示浏览器所支持的语言类型
    Connection:允许客户端和服务器指定与请求/响应连接有关的选项,例如这是为Keep-Alive则表示保持连接。
    Transfer-Encoding:告知接收端为了保证报文的可靠传输,对报文采用了什么编码方式。
  • 响应报头:(用于服务器传递自身信息的响应,常见的响应报头)
    Location:用于重定向接受者到一个新的位置,常用在更换域名的时候
    Server:包含可服务器用来处理请求的系统信息,与User-Agent请求报头是相对应的
    实体报头:(实体报头用来定于被传送资源的信息,既可以用于请求也可用于响应。请求和响应消息都可以传送一个实体,常见的实体报头为)
    Content-Type:发送给接收者的实体正文的媒体类型
    Content-Lenght:实体正文的长度
    Content-Language:描述资源所用的自然语言,没有设置则该选项则认为实体内容将提供给所有的语言阅读
    Content-Encoding:实体报头被用作媒体类型的修饰符,它的值指示了已经被应用到实体正文的附加内容的编码,因而要获得Content-Type报头域中所引用的媒体类型,必须采用相应的解码机制。
    Last-Modified:实体报头用于指示资源的最后修改日期和时间
    Expires:实体报头给出响应过期的日期和时间

2、HTTPS协议:

HTTPS (Hyper Text Transfer Protocol over SecureSocket Layer)是以安全为目标的 HTTP 通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性 。HTTPS 在HTTP 的基础下加入SSL 层,HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL。 HTTPS 存在不同于 HTTP 的默认端口及一个加密/身份验证层(在 HTTP与 TCP 之间)。这个系统提供了身份验证与加密通讯方法。现在它被广泛用于万维网上安全敏感的通讯,例如交易支付等方面。

优点:

使用 HTTPS 协议可认证用户和服务器,确保数据发送到正确的客户机和服务器。
HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,要比 HTTP 协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。
HTTPS 是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本。

缺点:

相同网络环境下,HTTPS 协议会使页面的加载时间延长近 50%,增加 10%到 20%的耗电。此外,HTTPS 协议还会影响缓存,增加数据开销和功耗 [2] 。
HTTPS 协议的安全是有范围的,在黑客攻击、拒绝服务攻击和服务器劫持等方面几乎起不到什么作用 [2] 。
最关键的是,SSL 证书的信用链体系并不安全。特别是在某些国家可以控制 CA 根证书的情况下,中间人攻击一样可行 [2] 。
成本增加。部署 HTTPS 后,因为 HTTPS 协议的工作要增加额外的计算资源消耗,例如 SSL 协议加密算法和 SSL 交互次数将占用一定的计算资源和服务器成本。在大规模用户访问应用的场景下,服务器需要频繁地做加密和解密操作,几乎每一个字节都需要做加解密,这就产生了服务器成本。随着云计算技术的发展,数据中心部署的服务器使用成本在规模增加后逐步下降,相对于用户访问的安全提升,其投入成本已经下降到可接受程度 [4] 。

3、HTTP与HTTPS的区别:

Android网络编程_第2张图片
Android网络编程_第3张图片

二、Android的网络编程:

1、Http通讯方式:

  • HttpUrlConnection
    在Android 2.2版本以及之前的版本使用HttpClient是较好的选择,而在Android 2.3版本及以后,HttpURLConnection则是最佳的选择,它的API简单,体积较小,因而非常适用于Android项目。压缩和缓存机制可以有效地减少网络访问的流量,在提升速度和省电方面也起到了较大的作用。另外在Android 6.0版本中,HttpClient库被移除了,HttpURLConnection则是以后我们唯一的选择。

HttpURLConnection使用的注意事项:

1.使用setConnectTimeout()方法设置连接超时,当网络不好时,Android系统会在超过设置时间后收回资源,中断操作。
2.通过getResponseCode()对响应码进行判断,如果返回的响应码为200,则表示连接成功
3.在对大文件操作时,要将文件写到SDCard上,不要直接写到手机内存上
4.操作大文件时,要一边从网络上读取,一边往SDCard上写入,减少手机内存的使用
5.对文件流操作完毕后要及时关闭
.Android4.0后所有网络通信的操作都不能在主线程进行,需要使用独立的线程完成

Android URL通信:

HttpURLConnection访问HTTP资源的步骤:
① 根据URL地址创建URL对象
② 使用URL对象的openConnection()方法获取HttpURLConnection对象
③ 设置连接的属性,包括GET/POST请求方式
④ 输入、输出数据
⑤ 关闭输入、输出流
⑤ 在AndroidManifest配置文件中设置访问INTERNET的权限

  • HttpClient
    HttpClient是Apache开源组织提供的一个开源的项目,从名字上就可以看出,它是一个简单的HTTP客户端(并不是浏览器),可以发送HTTP请求,接受HTTP响应。但是不会缓存服务器的响应,不能执行HTTP页面中签入嵌入的JS代码,自然也不会对页面内容进行任何解析、处理,这些都是需要开发人员来完成的。

HttpClient其实是一个interface类型,HttpClient封装了对象需要执行的Http请求、身份验证、连接管理和其它特性。从文档上看,HttpClient有三个已知的实现类分别是:AbstractHttpClient, AndroidHttpClient, DefaultHttpClient,会发现有一个专门为Android应用准备的实现类AndroidHttpClient,当然使用常规的DefaultHttpClient也可以实现功能,但是既然开发的是Android应用程序,还是使用Android专有的实现类,一定有其优势。

2、Socket通信方式:

Socket中文意思为插座的意思,专业术语称之为套接字,它把TCP/IP封装成了调用接口供开发者调用,也就是说开发者可以通过调用Socket相关API来实现网络通讯。在Java中也存在Socket相关API,主要分为两个,分别是基于UDP传输协议的Socket和基于TCP传输协议的Socket。

三、Android常用的网络编程框架:

  1. Volley
    Google官方推出的一套小而巧的异步请求库,支持HttpClient (Android 6.0之后不再支持)、HttpURLConnection
    基于网络队列,适合小数据频繁通信,请求线程池默认大小为4
  2. OkHttp
    高性能的http库,支持同步、异步,而且支持http2、websocket协议,api简洁易用,实现了http缓存
    Android网络访问的源码已用OkHttp代替了HttpURLConnection
  3. Retrofit:
    基于OkHttp封装的一套RESTful网络请求框架,底层默认采用OkHttp
  4. 目前网络框架的最好选择:RxJava + Retrofit + OkHttp

OKHttp:

(一)OkHttp开发基本思路:

  1. 0kHttp的每次网络请求是一个Request,提供Request必要的参数url、header等,基于Request构造出一个Call对象,再调用它的execute()方法,就能取得Web Server回复的数据

  2. 如果同步调用,需要在独立的线程中执行,使用异步调用,则采用回调的方式执行,在内部封装了一个请求队列。

  3. OkHttp依赖另一个组件okio完成高性能的I/O操作

  4. 基本用法:

  • 新建一个OkHttpClient对象
  • 通过Request.Builder对象新建一个Request对象
  • 通过Request对象构造Call对象,调用enqueue()以异步的方式将call加入调度队列,等待request执行完成
  • 通过Call对象的Callback对象返回执行结果

(二)特点:

  • 0KHttp是Android版Http客户端,非常高效,支持SPDY、连接池、GZIP和 HTTP缓存。
  • 默认情况下,OKHttp会自动处理常见的网络问题,像二次连接、SSL的握手问题。
  • 如果应用程序集成了OKHttp,Retrofit默认会使用OKHttp处理其他网络层请求。
  • 从Android4.4开始,HttpURLConnection的底层实现采用了okhttp。

(三)get异步请求:

  • 在另外的工作线程中执行http请求,请求时不会阻塞当前的线程,所以可以在Android主线程中使用。
  • 异步请求需要加入到一个请求队列中,并且要指定回调方法。

Get方法:

 private void get(String url) {
    final Request request = new Request.Builder().url(url)
        .header("user-agent","Mozilla/5.0(Windows NT 6.3; WOW64) AppleWebKit/537.36(KHTML,like Gecko) Chrome/51.0.2704.7 Safari/573.36")
        .addHeader("Accept","application/json")
        .build();
    OkHttpClient client = HttpsUtil.handleSSLHandshakeByOkHttp();
    client.newCall(request).enqueue(new Callback() {
      @Override public void onFailure(@NotNull Call call, @NotNull final IOException e) {
        Log.e(TAG,e.getMessage());
        runOnUiThread(new Runnable() {
          @Override public void run() {
            textView1.setText("获取失败,"+e.getMessage());
          }
        });

      }

      @Override public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
        if (response.isSuccessful()){
          String json = response.body().string();
          final Ip ip = JSON.parseObject(json,Ip.class);
          runOnUiThread(new Runnable() {
            @Override public void run() {
              if (ip.getCode() != 0){
                textView1.setText("未获得数据");
              }else {
                IpData data = ip.getData();
                textView1.setText(data.getiP()+","+data.getArea());
              }
            }
          });
        }else {
          Log.e(TAG,response.body().string());
        }
      }
    });
  }

Post方法:

  private void post(String url, Map<String, String> params) {
    RequestBody body = setRequestBody(params);
    Request request = new Request.Builder().url(url).post(body)
        .header("user-agent","Mozilla/5.0(Windows NT 6.3; WOW64) AppleWebKit/537.36(KHTML,like Gecko) Chrome/51.0.2704.7 Safari/573.36")
        .addHeader("Accept","application/json")
        .build();
    OkHttpClient client = HttpsUtil.handleSSLHandshakeByOkHttp();
    client.newCall(request).enqueue(new Callback() {
      @Override public void onFailure(@NotNull Call call, @NotNull IOException e) {
        Log.e("okActivity",e.getMessage());

      }

      @Override public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
        if (response.isSuccessful()){
          String json = response.body().string();
          final Ip ip = JSON.parseObject(json,Ip.class);
          runOnUiThread(new Runnable() {
            @Override public void run() {
              if (ip.getCode() != 0){
                textView1.setText("未获得数据");
              }else {
                IpData data = ip.getData();
                textView1.setText(data.getiP()+","+data.getArea());
              }
            }
          });
        } else {
          Log.e(TAG,response.body().string());
        }

      }
    });

  }

四、JSON数据解析:

1.概述:

  • JSON:JavaScript Object Notation,最初是针对JavaScript而设计,能够很方便地在字符串和JavaScript对象中进行转换。后来成为了一种世界通用的数据交换标准,独立于具体的编程语言。
  • 与XML相比,JSON语法简明,格式紧凑,易读易懂,数据传输量小,在移动互联时代,这些特点有着巨大的吸引力,因此,JSON成为了XML的替代者而被广泛应用。

2.JSON的属性值的类型:

数字(整数或浮点数)
字符串(在双引号中)
逻辑值(true 或 false)
数组(在方括号中)
对象(在花括号中)
null

3.创建JSON字符串:

当需要创建JSON字符串时,new一个JSONObject或者JSONArray对象,使用它们的put系列方法向其中追加数据,根据实际情况组合装配出JSONObject或JSONArray对象。
完成对象的装配工作之后,调用JSONObject或JSONArray的toString()方法即可生成JSON字符串

4.解析JSON字符串:

首先区分一下JSON字符串是单个对象还是数组,然后以
这个字符串作为参数,new一个JSONObject或者是JSONArray对象,Android内置的JSON解析组件就会解析JSON字符串,自动完成JSONObject或者是JSONArray对象的装配工作。
得到JSONObject或者是JSONArray对象引用之后,调用它的get系列方法,就能提取出JSON字符串中特定属性的值。

5.Gson工作原理:

Android网络编程_第4张图片

你可能感兴趣的:(Android)