面试问题
- Http协议概述
- 为什么OkHttp使用Socket而不是HttpUrlConnection
- OkHttp的核心类有哪些
- OkHttp的流程
- 构建者在OkHttp中的使用
- 责任链模式在OkHttp中的使用
- OkHttp对于网络请求都有哪些优化
- Http以及Https原理简单介绍下,加密过程是怎么做的
Http协议概述
指客户端和服务器之间通信时,发送的数据,需要遵守的规则,叫 HTTP 协议。HTTP 协议中的数据又叫报文。
客户端给服务器发送数据叫请求,服务器给客户端回传数据叫响应。
Get请求有请求行,请求头。
Post请求多了空行和请求体。
为什么OkHttp使用Socket而不是HttpUrlConnection
HttpUrlConnection也是通过Socket使客户端和服务端进行连接,而OkHttp直接使用Socket可以更大程度地实现自己想要实现的功能,更大程度地定制功能。
OkHttp的核心类有哪些
- OkHttpClient:整个框架的客户端类,OkHttpClient强烈建议全局单例使用,因为每一个OkHttpClient都有自己单独的连接池和线程池,复用连接池和线程池能够减少延迟、节省内存
- ConnectionPool:管理HTTP和HTTP / 2连接的重用,以减少网络延迟。 相同Address的HTTP请求可以共享Connection。 此类实现了哪些连接保持打开以供将来使用的策略
- Request:封装请求报文信息的对象,比如请求url,请求方法,超时时间,还有各种请求头
- Call:一个Call表示一个为执行而准备的请求,一个接口
- RealCall:Call的实现类,它是连接Request和Response的桥梁
- Response:请求响应的封装对象
- Dispatcher:分发器类,维护同步请求和异步请求的状态,内部维护了一个线程池,用于执行网络请求的线程;同时还维护了三个请求队列,一个是正在进行异步请求的队列(包含了已取消但未完成的请求),一个是处于等待执行的异步请求队列,最后一个是正在进行同步请求的队列(包含了已取消但未完成的请求)
- Interceptor:拦截器类,可以观察修改我们的请求和响应,是一个接口,有五个实现类,它们形成一个拦截器链,依次对我们的请求响应做处理
- RetryAndFollowUpInterceptor:Interceptor实现类之一,是网络请求失败时进行重连及服务器返回当前请求需要进行重定向的拦截器
- BridgeInterceptor:桥接连接器,主要是进行请求前的一些操作,将我们的请求设置成服务器能识别的请求,比如设置一系列头部信息,比如设置请求内容长度,编码,gzip压缩,cookie等
- CacheInterceptor:缓存拦截器,这个就很明显了,作用是缓存请求和响应,比如同一个请求之前发生过,这次就不需要重新构建了,直接从缓存取;响应同理
- ConnectInterceptor:连接拦截器,为当前请求找到一个合适的连接,比如如果从连接处中可以找到能复用的连接,就不要再创建新的连接了
- CallServerInterceptor:连接服务器拦截器,负责向服务器发送真正的请求,接受服务器的响应
OkHttp的流程
第一条主线-入队操作
// 构建OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
// 构建Request
Request request = new Request.Builder().url(url).build();
// 通过request创建RealCall对象,RealCall为Call的具体实现类
Call call = okHttpClient.newCall(request);
// 入队,添加回调
call.enqueue(new Callback() { // 此处省略Callback回调函数 }
第二条主线-网络访问操作
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
// 添加自定义拦截器
interceptors.addAll(client.interceptors());
// 重试和重定向拦截器
interceptors.add(retryAndFollowUpInterceptor);
// 桥拦截器
interceptors.add(new BridgeInterceptor(client.cookieJar()));
// 缓存拦截器
interceptors.add(new CacheInterceptor(client.internalCache()));
// 连接拦截器
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
// 请求服务器拦截器
interceptors.add(new CallServerInterceptor(forWebSocket));
// 责任链设计模式调用代码
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
构建者在OkHttp中的使用
当一个类的内部数据过于复杂的时候,比如OkHttpClient中包含Dispatcher,Proxy,ProxySelector,CookieJar,Cache,SocketFactory等等对象,Request中也包含了HttpUrl,method,Headers,RequestBody,tag等对象;这些对象说多不多,说少也不少,但它们都有一个共同点:很多参数都是不需要我们传递的,比如这两个对象在具体构建时的代码如下:
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
Request request = new Request.Builder().url(url).build();
OkHttpClient和Request中虽然包含了多个参数,但这些参数对于用户来说,是可传可不传的,在上述代码中只有在构建Requset时通过Builder.url(url).build()传入了一个url参数;这就相当于,如果我们不传入参数,构建者模式会帮我们创建默认的参数;如果传入参数,构建者模式则会用我们传入的替换默认的参数;
- 优点:我们不再关注OkHttpClient/Request的构建细节,不用每次构建时都传入大量参数,只需要传递我们关心的参数,非常易用;
- 缺点:整个代码看上去会有“代码冗余”的感觉,对于不了解设计模式的人来说会觉得生涩难懂;
责任链模式在OkHttp中的使用
责任链模式(Chain of Responsibility Pattern)为请求创建一个接收者对象的链。这种模式让请求的发送者和接收者进行解耦。在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果当前接收者无法处理该请求,则会传递到下一个接收者,依此类推;
如果你非常想念你异地的女朋友,你决定这个周末无论如何都要去她的城市见她,于是你查询了去她城市的交通方式:飞机,高铁,大巴,租车,骑摩托这五种方式(方便的程度按照顺序来),于是你先买飞机票,如果买到了,你就不考虑其他方式,如果没买到,就选择买高铁,如果买到了高铁票就不考虑大巴,如果高铁票也没有,则考虑大巴,如果买到大巴票就不选择租车,如果买不到再租车......依次类推;只要在某一个节点被处理了(比如买到了飞机票),就不再继续选择后面的节点,反之则继续走向下一个节点。
- 优点:我们拥有多种“选择”,只要其中一个满足,就不用再继续深挖,浪费更多的时间;
- 缺点:需要先耗费一定的时间,做出一个预想方案以及方案的各个节点;如果不做方案,直接购买了飞机票,而且恰好买到了,则时间更省,但如果买不到,你就得重新去规划接下来怎么办。可能浪费更多的时间;
OkHttp对于网络请求都有哪些优化
对比一下就知道了,以前我用HttpClient和HttpURLConnection(注意URL都是大写)比较多,用在项目的时候,给用户的体验感觉总会出现这样那样的问题,比如跳转到一个新的页面的时候,内容就是加载不出来,简而言之就是不稳定。另外对于一些内存开销和系统开销都需要程序员自己来控制,比如线程池,甚至连接池的处理等等。其次,流量的优化问题自己处理起来也比较麻烦。
OKhttp出来了这些问题都解决了。
下面我们看看官方给的OkHttp的好处。
支持 SPDY ,共享同一个Socket来处理同一个服务器的所有请求
那什么是SPDY呢?
它是HTTP的加强(不是取代),基于TCP协议,说白了目的就是让网络请求更快了。
SPDY干了哪些事情做到这个的呢?
- 单个TCP连接支持并发的HTTP请求。
- 压缩报头和去掉不必要的头部来减少当前HTTP使用的带宽。
- 定义一个容易实现,在服务器端高效率的协议。通过减少边缘情况、定义易解析的消息格式来减少HTTP的复杂性。
- 强制使用SSL,让SSL协议在现存的网络设施下有更好的安全性和兼容性。
- 允许服务器在需要时发起对客户端的连接并推送数据。
- SPDY已被HTTP/2取代
如果SPDY不可用,则通过连接池来减少请求延时
什么叫连接池?两个主机建立连接是个很复杂的过程,经过多次数据包的交换,例如TCP的三次握手,每次连接都走这个过程岂不是很耗资源。连接池说白了就是就是为了避免每次都要经历这些连接过程,从而节省了资源,耗时更短。
无缝的支持GZIP来减少数据流量
小伙伴不知道什么是GZIP,没事,百度百科有讲解。大流量的WEB站点常常使用GZIP的压缩技术来让用户感受更快的速度。这一般是指WWW服务器中安装的一个功能,当有人来访问这个服务器中的网站时,服务器中的这个功能就将网页内容压缩后传输到来访的电脑浏览器中显示出来.一般对纯文本内容可压缩到原大小的40%.这样传输就快了,效果就是你点击网址后会很快的显示出来(优点),当然这也会增加服务器的负载(缺点)。
缓存响应数据来减少重复的网络请求
OkHttp只会对get请求进行缓存,post请求是不会进行缓存,这也是有道理的,因为get请求的数据一般是比较持久的,而post一般是交互操作,没太大意义进行缓存。我们get请求有时有不一样的需求,有时需要进行缓存,有时需要直接从网络获取,有时只获取缓存数据,这些处理,okhttp都有帮我们做了,我们做的只需要设置就是了。
Http以及Https原理简单介绍下,加密过程是怎么做的
HTTP是一个基于TCP/IP通信协议来传递数据的协议,传输的数据类型为HTML 文件,、图片文件, 查询结果等。
HTTP协议一般用于B/S架构()。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。
HTTPS 协议(HyperText Transfer Protocol over Secure Socket Layer):一般理解为HTTP+SSL/TLS,通过 SSL证书来验证服务器的身份,并为浏览器和服务器之间的通信进行加密。
http和https使用连接方式不同,默认端口也不一样,http是80,https是443。
SSL加密过程:
- 首先客户端通过URL访问服务器建立SSL连接。
- 服务端收到客户端请求后,会将网站支持的证书信息(证书中包含公钥)传送一份给客户端。
- 客户端的服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
- 客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
- 服务器利用自己的私钥解密出会话密钥。
- 服务器利用会话密钥加密与客户端之间的通信。
网友评论