Android面试题-网络相关

TCP 的三次握手和四次挥手

第一次握手:客户端发送 syn 包(syn=j)到服务器,并进入 SYN_SEND 状态,等待服务器确认;
第二次握手:服务器收到 syn 包,必须确认客户的 SYN(ack=j+1),同时自己也发送一个 SYN包(syn=k),即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态;
第三次握手:客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACK(ack=k+1),此包发送完毕,客户端和服务器进入 ESTABLISHED 状态,完成三次握手。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP 连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开 TCP 连接的请求

断开过程需要经过“四次握手”
第一次挥手:客户端发送报文告诉服务器没有数据要发送了
第二次挥手:服务端收到,再发送给客户端告诉它我收到了
第三次挥手:服务端向客户端发送报文,请求关闭连接
第四次挥手:客户端收到关闭连接的请求,向服务端发送报文,服务端关闭连接

TCP(Transmission Control Protocol) 与 UDP(User Datagram Protocol) 的区别

  1. TCP 面向连接;UDP 是无连接的,即发送数据之前不需要建立连接
  2. TCP 提供可靠的服务。也就是说通过 TCP 连接传送的数据,无差错、不丢失、不重复;UDP 尽最大努力交付,即不保证可靠交付
  3. TCP 面向字节流,实际上是 TCP 把数据看成一连串无结构的字节流;UDP 是面向报文的。UDP 没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如 IP 电话、实时视频会议等)
  4. 每一条 TCP 连接只能是点到点的;UDP 支持一对一、一对多、多对一和多对多的交互通信
  5. TCP 首部开销 20 字节;UDP 的首部开销小,只有 8 个字节
  6. TCP 的逻辑通信信道是全双工的可靠信道,UDP 则是全双工的不可靠信道

TCP 与 UDP 的应用

TCP:HTTP、FTP、SMTP、TENET、POP3、Finger、NNTP、IMAP4
UDP:BOOTP、DHCP、NTP、TFTP、SNMP

HTTP 协议

HTTP 协议是一个基于请求与响应模式的面向连接、无状态,应用层的一种协议,支持 C/S模式,简单快速、灵活。
简单快速:协议简单,通信速度快
灵活:允许传输任意类型的数据对象,由 Content-Type 标记
无连接:每次处理一个请求,处理完成后既断开
无状态:对事务处理没有记忆能力
HTTP 有两种报文:请求报文和响应报文
请求报文由请求行、请求报头和请求数据组成。请求行:抓包第一行,包括请求方法、URL 和 HTTP 版本;请求报头:指的就是题目中“里面的协议头部”;请求数据:指 POST 方式提交的表单数据
响应报文由状态行、响应报头和响应正文组成。状态行:状态码;响应报头:同请求报头;响应正文:服务器返回的资源数据
接下来是 HTTP 头部,既请求报头和响应报头,统称消息报头,消息报头可以分为通用报头、请求报头、响应报头、实体报头等。通用报头和实体报头既可以出现在请求报头中,也可以出现在响应报头中,
通用报头包含的字段如:Date、Connection、Cache-Control;
实体报头中有:Content-Type、Content-Length、Content-Language、Content-Encoding;
请求报头中包含的字段有:Host、User-Agent、Accept-Encoding、Accept-Language、Connection;
响应报头包含的字段:Location、Server

HTTP1.0、HTTP1.1 、 HTTP2.0 的区别

HTTP1.0 和 HTTP1.1 的区别:

  1. 长连接(Persistent Connection):HTTP1.1 支持长连接和请求的流水线处理,在一个 TCP 连接上可以传送多个 HTTP 请求和响应,减少了建立和关闭连接的消耗和延迟,在 HTTP1.1 中默认开启长连接 keep-alive,一定程度上弥补了 HTTP1.0 每次请求都要创建连接的缺点。HTTP1.0 需要使用 keep-alive 参数来告知服务器端要建立一个长连接。
  2. 节约带宽:HTTP1.0 中存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能。HTTP1.1 支持只发送 header信息(不带任何 body 信息),如果服务器认为客户端有权限请求服务器,则返回 100,客户端接收到 100 才开始把请求 body 发送到服务器;如果返回 401,客户端就可以不用发送请求 body 了节约了带宽。
  3. HOST 域:在 HTTP1.0 中认为每台服务器都绑定一个唯一的 IP 地址,因此,请求消息中的URL 并没有传递主机名(hostname),HTTP1.0 没有 host 域。随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP 地址。HTTP1.1 的请求消息和响应消息都支持 host 域,且请求消息中如果没有 host 域会报告一个错误(400 Bad Request)。
  4. 缓存处理:在 HTTP1.0 中主要使用 header 里的 If-Modified-Since,Expires 来做为缓存判断的标准,HTTP1.1 则引入了更多的缓存控制策略例如 Entity tag,If-Unmodified-Since, If-Match, If-None-Match 等更多可供选择的缓存头来控制缓存策略。
  5. 错误通知的管理:在 HTTP1.1 中新增了 24 个错误状态响应码,如 409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。

HTTP1.1 和 HTTP2.0 的区别

  1. 多路复用:HTTP2.0 使用了多路复用的技术,做到同一个连接并发处理多个请求,而且并发请求的数量比 HTTP1.1 大了好几个数量级。HTTP1.1 也可以多建立几个 TCP 连接,来支持处理更多并发的请求,但是创建 TCP 连接本身也是有开销的。
  2. 头部数据压缩:在 HTTP1.1 中,HTTP 请求和响应都是由状态行、请求/响应头部、消息主体三部分组成。一般而言,消息主体都会经过 gzip 压缩,或者本身传输的就是压缩过后的二进制文件,但状态行和头部却没有经过任何压缩,直接以纯文本传输。随着 Web 功能越来越复杂,每个页面产生的请求数也越来越多,导致消耗在头部的流量越来越多,尤其是每次都要传输 UserAgent、Cookie 这类不会频繁变动的内容,完全是一种浪费。HTTP1.1 不支持 header 数据的压缩,HTTP2.0 使用 HPACK 算法对 header 的数据进行压缩,这样数据体积小了,在网络上传输就会更快。
  3. 服务器推送:服务端推送是一种在客户端请求之前发送数据的机制。网页使用了许多资源:HTML、样式表、脚本、图片等等。在 HTTP1.1 中这些资源每一个都必须明确地请求。这是一个很慢的过程。浏览器从获取 HTML 开始,然后在它解析和评估页面的时候,增量地获取更多的资源。因为服务器必须等待浏览器做每一个请求,网络经常是空闲的和未充分使用的。为了改善延迟,HTTP2.0 引入了 server push,它允许服务端推送资源给浏览器,在浏览器明确地请求之前,免得客户端再次创建连接发送请求到服务器端获取。这样客户端可以直接从本地加载这些资源,不用再通过网络。

HTTPS 协议

HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的 HTTP通道,简单讲是 HTTP 的安全版。HTTP 是应用层协议,位于 HTTP 协议之下是传输协议 TCP。TCP 负责传输,HTTP 则定义了数据如何进行包装,在 HTTP 跟 TCP 中间多加了一层加密层TLS/SSL,SSL 是个加密套件,负责对 HTTP 的数据进行加密。TLS 是 SSL 的升级版。现在提到HTTPS,加密套件基本指的是 TLS。

传输加密的流程:Http 是应用层将数据直接给到 TCP 进行传输,Https 是应用层将数据给到TLS/SSL,将数据加密后,再给到 TCP 进行传输。HTTPS 是如何加密数据的:一般来说,加密分为对称加密、非对称加密

  1. 对称加密:对称加密的意思就是,加密数据用的密钥,跟解密数据用的密钥是一样的。对称加密的优点在于加密、解密效率通常比较高。缺点在于,数据发送方、数据接收方需要协商,共享同一把密钥,并确保密钥不泄露给其他人。传输过程中容易被截获。
  2. 非对称加密:非对称加密的意思就是,加密数据用的密钥(公钥),跟解密数据用的密钥(私钥)是不一样的。网上一个很形象的例子:小服还是挺聪明的,得意了一会之后,小服意识到了密钥会被截取这个问题。倔强的小服又想到了另外一种方法:用非对称加密的方法来加密数据。该方法是这样的:小服和小客都拥有两把钥匙,一把钥匙的公开的(全世界都知道也没关系),称之为公钥;而另一把钥匙是保密(也就是只有自己才知道),称之为私钥。并且用公钥加密的数据,只有对应的私钥才能解密;用私钥加密的数据,只有对应的公钥才能解密。所以在传输数据的过程中,小服在给小客传输数据的过程中,会用小客给他的公钥进行加密,然后小客收到后,再用自己的私钥进行解密。小客给小服发消息的时候,也一样会用小服给他的公钥进行加密,然后小服再用自己的私钥进行解密。这样,数据就能安全着到达双方。是什么原因导致非对称加密这种方法的不安全性呢?它和对称加密方法的不安全性不同。非对称加密之所以不安全,是因为小客收到了公钥之后,无法确定这把公钥是否真的是小服。解决的办法就是数字证书:小服再给小客发公钥的过程中,会把公钥以及小服的个人信息通过 Hash 算法生成消息摘要,为了防止摘要被人调换,小服还会用 CA 提供的私钥对消息摘要进行加密来形成数字签名,当小客拿到这份数字证书之后,就会用 CA提供的公钥来对数字证书里面的数字签名进行解密得到消息摘要,然后对数字证书里面小服的公钥和个人信息进行 Hash 得到另一份消息摘要,然后把两份消息摘要进行对比,如果一样,则证明这些东西确实是小服的,否则就不是。

谈谈你对 WebSocket 的理解

首先,Websocket 是一个持久化的协议,相对于 HTTP 这种非持久的协议来说。HTTP 的生命周期通过 Request 来界定,也就是一个 Request 一个 Response,那么在 HTTP1.0 中,这次HTTP 请求就结束了。在 HTTP1.1 中进行了改进,使得有一个 keep-alive,也就是说,在一个HTTP 连接中,可以发送多个 Request,接收多个 Response。但是请记住 Request = Response,在 HTTP 中永远是这样,也就是说一个 request 只能有一个 response。而且这个 response 也是被动的,不能主动发起。Websocket 是基于 HTTP 协议的,或者说借用了 HTTP 的协议来完成一部分握手。但是 Websocket 只需要一次 HTTP 握手,所以说整个通讯过程是建立在一次连接/状态中,也就避免了 HTTP 的非状态性,服务端会一直知道你的信息,直到你关闭请求

HTTP 的 Get 和 Post 的区别

HTTP 是应用层的协议,底层基于 TCP/IP 协议,所以本质上 Get 和 Post 请求都是 TCP 请求。所以二者的区别都是体现在应用层上(HTTP 的规定和 C/S 的限制)

  1. 参数的传输方式:GET 参数通过 URL 传递,POST 放在 Request body 中。
  2. Get 请求在 URL 中传送的参数是有长度限制的,而 POST 没有。
  3. 对于 GET 方式的请求,浏览器会把 Http Header 和 data 一并发送出去,服务器响应 200(返回数据);而对于 POST,浏览器先发送 Header,服务器响应 100 continue,浏览器再发送 data,服务器响应 200 ok(返回数据)。不过要注意,并不是所有浏览器都会在 POST 中发送两次包,比如火狐
  4. 对参数的数据类型,GET 只接受 ASCII 字符,而 POST 没有限制。
  5. GET 比 POST 不安全,因为参数直接暴露在 URL 上,所以不能用来传递敏感信息。
  6. GET 请求只能进行 URL 编码,而 POST 支持多种编码方式。
  7. GET 在浏览器回退时是无害的,而 POST 会再次提交请求。
  8. GET 产生的 URL 地址可以被 Bookmark,而 POST 不可以。
  9. GET 请求会被浏览器主动 cache,而 POST 不会,除非手动设置。

Socket 和 Http 的区别

HTTP 协议:简单的对象访问协议,对应于应用层。HTTP 协议是基于 TCP 连接的
TCP 协议:对应于传输层
IP 协议:对应与网络层,TCP/IP 是传输层协议,主要解决数据如何在网络中传输;而 Http是应用层协议,主要解决如何包装数据。
Socket 是对 TCP/IP 协议的封装,Socket 本身并不是协议,而是一个调用接口(API),通过 Socket,我们才能使用 TCP/IP 协议。
Http 连接:Http 连接就是所谓的短连接,及客户端向服务器发送一次请求,服务器端响应后连接即会断掉。Socket 连接:Socket 连接及是所谓的长连接,理论上客户端和服务端一旦建立连接,则不会主动断掉;但是由于各种环境因素可能会是连接断开,比如说:服务器端或客户端主机 down 了,网络故障或者两者之间长时间没有数据传输,网络防火墙可能会断开该连接已释放网络资源。所以当一个 Socket 连接中没有数据的传输,那么为了维持连续的连接需要发送心跳消息,具体心跳消息格式是开发者自己定义的。

描述一次网络请求的流程

  1. 域名解析:浏览器会先搜索自身 DNS 缓存且对应的 IP 地址没有过期;若未找到则搜索操作系统自身的 DNS 缓存;若还未找到则读本地的 hotsts 文件;还未找到会在 TCP/IP 设置的本地 DNS 服务器上找,如果要查询的域名在本地配置的区域资源中,则完成解析;否则根据本地 DNS 服务器会请求根 DNS 服务器;根 DNS 服务器是 13 台根 DNS,会一级一级往下找。
  2. TCP 三次握手:客户端先发送 SYN=1,ACK=0,序列号 seq=x 报文;(SYN 在连接建立时用来同步序号,SYN=1,ACK=0 代表这是一个连接请求报文,对方若同意建立连接,则应在响应报文中使 SYN=1,ACK=1)服务器返回 SYN=1,ACK=1,seq=y,ack=x+1;客户端再一次确认,但不用 SYN 了,回复服务端,ACK=1,seq=x+1, ack=y+1
  3. 建立 TCP 连接后发起 HTTP 请求:客户端按照指定的格式开始向服务端发送 HTTP 请求,HTTP 请求格式由四部分组成,分别是请求行、请求头、空行、消息体,服务端接收到请求后,解析 HTTP 请求,处理完逻辑,最后返回一个具有标准格式的 HTTP 响应给客户端。
  4. 服务器响应 HTTP:请求服务器接收处理完请求后返回一个 HTTP 响应消息给客户端,HTTP响应信息格式包括:状态行、响应头、空行、消息体
  5. 浏览器解析 HTML 代码,请求 HTML 代码中的资源:浏览器拿到 HTML 文件后,就开始解析其中的 HTML 代码,遇到 js/css/image 等静态资源时,向服务器发起一个 HTTP 请求,如果返回 304 状态码,浏览器会直接读取本地的缓存文件。否则开启线程向服务器请求下载。
  6. 浏览器对页面进行渲染并呈现给用户
  7. TCP 的四次挥手:当客户端没有东西要发送时就要释放连接(提出中断连接可以是 Client也可以是 Server),客户端会发送一个 FIN=1 的没有数据的报文,进入 FIN_WAIT 状态,服务端收到后会给客户端一个确认,此时客户端不能发送数据,但可接收信息。

网络分层

OSI 七层模型(OSI 七层协议模型)主要是:应用层(Application)、表示层(Presentation)、
会话层(Session)、传输层(Transport)、网络层(Network)、数据链路层(Data Link)、物
理层(Physical)
TCP/IP 五层模型(TCP/IP 五层模型):应用层(Application)、传输层(Transport)、网络层
(Network)、 数据链路层(Data Link)、物理层(Physical)

网络请求缓存处理?OkHttp 如何处理网络缓存?

1.网络缓存优先考虑强制缓存,再考虑对比缓存
--首先判断强制缓存中的数据的是否在有效期内。如果在有效期则直接使用缓存,如果过了有效期则进入对比缓存
--在对比缓存过程中,判断 ETag 是否有变动,如果服务端返回没有变动,说明资源未改变,使用缓存。如果有变动,判断 Last-Modified
--判断 Last-Modified,如果服务端对比资源的上次修改时间没有变化,则使用缓存,否则重新请求服务端的数据,并作缓存工作
2.Okhttp 缓存
开启使用 Okhttp 的缓存其实很简单,只需要给 OkHttpClient 对象设置一个 Cache 对象即可,创建一个 Cache 时指定缓存保存的目录和缓存最大的大小即可
//新建一个 cache,指定目录为外部目录下的 okhttp_cache 目录,大小为 100M
Cache cache = new Cache(new File(Environment.getExternalStorageDirectory() +
"/okhttp_cache/"), 100 * 1024 * 1024);
//将 cache 设置到 OkHttpClient 中,这样缓存就开始生效了
OkHttpClient client = new OkHttpClient.Builder().cache(cache).build();
相关的类有:
1.CacheControl(HTTP 中的 Cache-Control 和 Pragma 缓存控制):指定缓存规则
2.Cache(缓存类)
3.DiskLruCache(文件化的 LRU 缓存类)
1.读取缓存:
先获限 OkHttpClient 的 Cache 缓存对象,就是上面创建 OkHttpClient 设置的 Cahce; 传 Request请求到 Cache 的 get 方法查找缓存响应数据 Response;构造一个缓存策略,再调用它的 get()去 决 策 使 用 网 络 请 求 还 是 缓 存 响 应 。 若 使 用 缓 存 , 它 的 cacheResponse 不 为 空 ,networkRequest 为空,用缓存构造响应直接返回。若使用请求,则 cacheResponse 为空,networkRequest 不为空,开始网络请求流程。
Cache 的 get 获取缓存方法:计算 request 的 key 值(请求 url 进行 md5 加密),根据 key 值去 DisLruCache 查找是否存在缓存内容,存在则创建 Entry 实体。ENTRY_METADATA 代表响应头信息,ENTRY_BODY 代表响应体信息。如果缓存存在,在指定目录下会有两个文件****.0*****.1 分别存储某个请求缓存响应头和响应体信息。CacheStrategy 的 get 方法:1)若缓存响应为空 2)请求是 https 但缓存响应没有握手信息 3)
请求和缓存响应都是不可缓存的 4)请求是 noCache,并且又包含 if-Modified-Since 或If-None-Match 则不使用缓存;再计算请求有效时间是否符合响应的过期时间,若响应在有效范围内,则缓存策略使用缓存,否则创建一个新的有条件的请求,返回有条件的缓存策略。
2.存储缓存流程:从 HttpEngine 的 readResponse()发送请求开始,判断 hasBody(userResponse),如果缓存的话,maybeCache()缓存响应头信息,unzip(cacheWritingResponse(storeRequest, userResponse))缓存响应体。

谈谈对 Volley 的理解

1、Volley 的特点
Volley 是谷歌大会上推出的网络通信框架(2.3 之前使用 HttpClient,之后使用HttpUrlConnection),它既可以访问网络获取数据,也可以加载图片,并且在性能方面进行了大幅度的调整,它的设计目的就是适合进行数据量不大但通信频繁的网络操作,而对于大数据量的操作,比如文件下载,表现很糟糕,因为 Volley 处理 http 返回的默认实现是BasicNetwork,它会把返回的流全部导入内存中,下载大文件会发生内存溢出
2、Volley 执行的过程
默认情况下,Volley 中开启四个网络调度线程和一个缓存调度线程,首先请求会加入缓存队列,缓存调度线程从缓存队列中取出线程,如果找到该请求的缓存就直接读取该缓存并解析,然后回调给主线程,如果没有找到缓存的响应,则将这个请求加入网络队列,然后网络调度线程会轮询取出网络队列中的请求,发起 http 请求,解析响应并将响应存入缓存,回调给主线程
3、Volley 为什么不适合下载上传大文件?为什么适合数据量小的频率高的请求?1.Volley 基于请求队列,Volley 的网络请求线程池默认大小为 4。意味着可以并发进行 4个请求,大于 4 个会排在队列中。并发量小所以适合数据量下频率高的请求 2.因为 Volley 下载文件会将流存入内存中(是一个小于 4k 的缓存池),大文件会导致内存溢出,所以不能下载大文件,不能上传大文件的原因和 1 中差不多,设想你上传了四个大文件,同时占用了 Volley 的四个线程,导致其他网络请求都阻塞在队列中,造成反应慢的现象

谈谈对 OkHttp 的理解

1、OKHttp 的特点
1.相较于 Volley,它的最大并发量为 64
2.使用连接池技术,支持 5 个并发的 socket 连接,默认 keepAlive 时间为 5 分钟,解决TCP 握手和挥手的效率问题,减少握手次数
3.支持 Gzip 压缩,且操作对用户透明,可以通过 header 设置,在发起请求的时候自动加入 header,Accept-Encoding: gzip,而我们的服务器返回的时候 header 中有Content-Encoding:gzip
4.利用响应缓存来避免重复的网络请求
5.很方便的添加拦截器,通常情况下,拦截器用来添加、移除、转换请求和响应的头部信息,比如添加公参等
6.请求失败,自动重连,发生异常时重连,看源码调用 recover 方法重连了一次
7.支持 SPDY 协议(SPDY 是 Google 开发的基于 TCP 的应用层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验。SPDY 并不是一种用于替代 HTTP 的协议,而是对HTTP 协议的增强。新协议的功能包括数据流的多路复用、请求优先级以及 HTTP 报头压缩。谷歌表示,引入 SPDY 协议后,在实验室测试中页面加载速度比原先快 64%)
8.使用 Okio 来简化数据的访问与存储,提高性能
2、OkHttp 的缺点
1.消息回来需要切到主线程,主线程要自己去写。
2.调用比较复杂,需要自己进行封装。
3.缓存失效:网络请求时一般都会获取手机的一些硬件或网络信息,比如使用的网络环境。同时为了信息传输的安全性,可能还会对请求进行加密。在这些情况下 OkHttp 的缓存系统就会失效了,导致用户在无网络情况下不能访问缓存。
3、OkHttp 框架中都用到了哪些设计模式
1.Builder 设计模式,如构建对象 OkHttpClient,还有单例模式
2.工厂方法模式,如源码中的接口 Call
3.观察者模式如 EventListener,监听请求和响应
4.策略模式
5.责任链模式,如拦截器

谈谈对 Retrofit 的理解

Retrofit 底层是基于 OkHttp 实现的,与其他网络框架不同的是,它更多使用运行时注解的方式提供功能
1、原理
通过 java 接口以及注解来描述网络请求,并用动态代理的方式生成网络请求的 request,然后通过 client 调用相应的网络框架(默认 okhttp)去发起网络请求,并将返回的 response通过 converterFactorty 转换成相应的数据 model,最后通过 calladapter 转换成其他数据方式(如 Rxjava Observable)
2、Retrofit 流程
1.通过解析网络请求接口的注解,配置网络请求参数
2.通过动态代理生成网络请求对象
3.通过网络请求适配器将网络请求对象进行平台适配
4.通过网络请求执行器发送网络请求
5.通过数据转换器解析服务器返回的数据
6.通过回调执行器切换线程(子线程 ->>主线程)
7.用户在主线程处理返回结果
3、Retrofit 优点
1.可以配置不同 HTTP Client 来实现网络请求,如 Okhttp、HttpClient 等
2.请求的方法参数注解都可以定制
3.支持同步、异步和 RxJava
4.超级解耦
5.可以配置不同的反序列化工具来解析数据,如 json、xml 等
6.框架使用了很多设计模式

HttpUrlConnection 和 OkHttp 的关系

Okhttp 中有 OkHttpUrlConnection 类,继承自 HttpUrlConnection

AsyncTask+HttpClient 和 AsyncHttpClient 有什么区别

AsyncHttpClient 是异步的 HttpClient

HttpClient 和 HttpUrlConnection 的区别

首先 HttpClient 和 HttpUrlConnection 这两种方式都支持 Https 协议,都是以流的形式进行上传或者下载数据,也可以说是以流的形式进行数据的传输,还有 ipv6,以及连接池等功能。HttpClient 这个拥有非常多的 API,所以如果想要进行扩展的话,并且不破坏它的兼容性的话,很难进行扩展,也就是这个原因,Google 在 Android6.0 的时候,直接就弃用了这个HttpClient。而 HttpUrlConnection 相对来说就是比较轻量级了,API 比较少,容易扩展,并且能够满足 Android 大部分的数据传输。比较经典的一个框架 Volley,在 2.3 版本以前都是使用 HttpClient,在 2.3 以后就使用了 HttpUrlConnection

Xutils、Volley、OkHttp、Retrofit 对比

Xutils:这个框架非常全面,可以进行网络请求,可以进行图片加载处理,可以数据储存,还可以对 view 进行注解,使用这个框架非常方便,但是缺点也是非常明显的,使用这个项目,会导致项目对这个框架依赖非常的严重,一旦这个框架出现问题,那么对项目来说影响非常大的。

Volley:Volley 是 Google 官方出的一套小而巧的异步请求库,该框架封装的扩展性很强,支持 HttpClient、HttpUrlConnection,甚至支持 OkHttp,而且 Volley 里面也封装了 ImageLoader,所以如果你愿意你甚至不需要使用图片加载框架,不过这块功能没有一些专门的图片加载框架强大,对于简单的需求可以使用,稍复杂点的需求还是需要用到专门的图片加载框架。Volley 也有缺陷,比如不支持 post 大数据,所以不适合上传文件。不过 Volley 设计的初衷本身也就是为频繁的、数据量小的网络请求而生。

OKhttp:Android 开发中是可以直接使用现成的 api 进行网络请求的。就是使用 HttpClient、HttpUrlConnection 进行操作。Okhttp 针对 Java 和 Android 程序,封装的一个高性能的 http请求库,支持同步、异步,而且 Okhttp 又封装了线程池,封装了数据转换,封装了参数的使用,错误处理等。API 使用起来更加的方便。但是我们在项目中使用的时候仍然需要自己在做一层封装,这样才能使用的更加的顺手。

Retrofit:Retrofit 是 Square 公司出品的默认基于 OkHttp 封装的一套 RESTful 网络请求框架,RESTful 是目前流行的一套 api 设计的风格,并不是标准。Retrofit 的封装可以说是很强大,里面涉及到一堆的设计模式,可以通过注解直接配置请求,可以使用不同的 http 客户端,虽然默认是用 http,可以使用不同 Json Converter 来序列化数据,同时提供对 RxJava 的支持,使用 Retrofit + OkHttp + RxJava + Dagger2 可以说是目前比较潮的一套框架,但是需要有比较高的门槛。

Volley VS OkHttp
Volley 的优势在于封装的更好,而使用 OkHttp 你需要有足够的能力再进行一次封装。而OkHttp 的优势在于性能更高,因为 OkHttp 基于 NIO 和 Okio,所以性能上要比 Volley 更快。IO 和 NIO 这两个都是 Java 中的概念,如果我从硬盘读取数据,第一种方式就是程序一直等,数据读完后才能继续操作这种是最简单的也叫阻塞式 IO,还有一种是你读你的, 程序接着往下执行,等数据处理完你再来通知我,然后再处理回调。而第二种就是 NIO 的方式,非阻塞式,所以 NIO 当然要比 IO 的性能要好了,而 Okio 是 Square 公司基于 IO 和 NIO 基础上做的一个更简单、高效处理数据流的一个库。理论上如果 Volley 和 OkHttp 对比的话,更倾向于使用 Volley,因为 Volley 内部同样支持使用 OkHttp,这点 OkHttp 的性能优势就没了,而且 Volley 本身封装的也更易用,扩展性更好些。

OkHttp VS Retrofit
毫无疑问,Retrofit 默认是基于 OkHttp 而做的封装,这点来说没有可比性,肯定首选 Retrofit。

Volley VS Retrofit
这两个库都做了不错的封装,但 Retrofit 解耦的更彻底,尤其 Retrofit2.0 出来,Jake 对之前1.0 设计不合理的地方做了大量重构,职责更细分,而且 Retrofit 默认使用 OkHttp,性能上也要比 Volley 占优势,再有如果你的项目如果采用了 RxJava,那更该使用 Retrofit。所以这两个库相比,Retrofit 更有优势,在能掌握两个框架的前提下该优先使用 Retrofit。但是 Retrofit门槛要比 Volley 稍高些,要理解他的原理,各种用法,想彻底搞明白还是需要花些功夫的,如果你对它一知半解,那还是建议在商业项目使用 Volley 吧。

你可能感兴趣的:(Android面试题-网络相关)