okhttp是一个非常好的网络开源库,下面是okhttp官网上的一些介绍:
HTTP is the way modern applications network. It’s how we exchange data & media. Doing HTTP efficiently makes your stuff load faster and saves bandwidth.
OkHttp is an HTTP client that’s efficient by default:
- HTTP/2 support allows all requests to the same host to share a socket.
- Connection pooling reduces request latency (if HTTP/2 isn’t available).
- Transparent GZIP shrinks download sizes.
- Response caching avoids the network completely for repeat requests.
okhttp的官网为:okhttp
重要类和结构
okhttp module
ConnectionSpec
指明了连接规范,包括信息有:是否tls,加密算法,tls协议版本,是否支持tls扩展等
OkHostnameVerifier
实现HostnameVerifier接口,提供验证服务器证书和host的功能
CertificatePinner
使用该类可以指定服务器端的证书必须包含的信息,如果没有,则会服务器证书验证失败
Authenticator
当服务器或者代理服务器需要验证客户端身份时,该类可以可以通过authenticate回调生成一个带有权限request进行验证,或者返回一个null不进行继续验证
ConnectionPool
该类用于重用HTTP连接已达到减少延迟的目的,同一个http地址可以共享一个Connection。
- connections:Deque
用于管理connection列表 - connectionBecameIdle
当connection变成idle时,会触发ConnectionPool的该方法。如果明确变成idle的connect标记noNewStream时,或者用户配置maxIdleConnections<=0,则直接从connection队列中移除该connection,否则通过notifyAll的方式触发cleanupRunnable进行clean操作。 - cleanupRunnable
该runnable用于根据特定的条件自动清除idle的connection。每当清除之后,会自动wait进行睡眠等待超时唤醒或者notify唤醒
OkHttpClient
该类主要用于记录用户关于网络需求的各项配置
- Builder:
用于配置初始化OKHttpClient所需参数,其中主要包括,protocols,connectionSpecs,hostNameVerifier, certificatePinner,cookieJar, Cache 等等 - static域中对Internal的instance进行了初始化
Request
该类用于生成一个网络请求,包含最基本的请求信息,url,method,headers,body,tag, cachecontrol。内部提供builder类用于生成Request。Request使用HttpUrl,Headers,CacheControl等工具类,方便解析和管理url和header,缓存机制
Response
和Request对应的类是Response。包含的基本信息有:request,protocol,code,message,handshake,body,networkResponse,cacheResponse,priorResponse
Dispatcher
- ExecutorService
线程管理池,用于执行各个队列中的call - runningSyncCalls:Deque
同步的RealCall会被push到该队列中 - runningAsyncCalls,readyAsyncCalls:Deque
异步的asyncCall会被push到runningAsyncCalls中,如果超过最大并行call的限制,会先放入readyAsyncCalls中进行存储,在慢慢往runningAsyncCalls移动
RealCall implements Call
当准备好Request时,可以通过OkHttpClient的newCall产生一个RealCall,来准备网络请求的发起。该类实现了Call接口,主要有同步请求execute,异步请求enqueue,取消cancel等操作
- excute()
同步执行网络请求,中间非常有意思的是使用了CloseGuard监听respond.body.close(CloseGuard。接着使用okhttpclient的dispatcher进行执行记录处理情况。真正执行请求是调用getResponseWithInterceptorChain方法中 - enqueue(Callback)
异步执行网络请求,通过内部类AsyncCall将自己进行包装成NamedRunnable,通过okhttpclient的dispatcher进行线程调用。最终网络请求发生在AsyncCall的execute中通过调用getResponseWithInterceptorChain进行123456789101112131415161718//这里贴出getResponseWithInterceptorChain的核心代码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);return chain.proceed(originalRequest);}
Interceptor
这个接口扮演着一个非常重要的角色,任何一个请求可以被一个或者多个Interceptor组成的链表进行依次处理,用户可以设计自己的Interceptor对一个请求的生命周期内进行自定义的处理,下面给出Interceptor的源码:
RealInterceptorChain
之所以Interceptor能按照依次处理,主要依赖于RealInterceptorChain的process实现,具体代码如下所示,在process的过程中,增加index,生成新的RealInterceptorChain,调用对应interceptor的intercept方法
Route
Route主要包含3个主要信息:Address,proxy,inetSocketAddress
RouteSelector
Route的选择器,该选择器通过Address和RouteDataBase进行初始化。RouteDataBase用于记录失败Route
proxies/nextProxyIndex
用于记录对应的proxy列表,nextProxyIndex用于记录当前proxy指针
每次初始话时,根据address信息初始化Proxy列表和指针inetSocketAddresses/nextInetSocketAddressIndex
用于记录对应的socket地址列表,nextInetSocketAddressIndex用于记录当前指针
每次更替Proxy时,需要重新reset inetSocketAddresses列表和指针postponedRoutes
用于记录需要推迟失败的route
StreamAllocation
用于处理Connection,Stream,Calls之间的关系。其中Connection代表和服务器链接的socket。Stream代表一次请求对(request/respond),而Call代表一组Stream,涉及到最初的request以及承接的request
release
主要工作为:将自身从绑定的RealConnection.allocations中移除,如果RealConnection.allocations空了,需要做对应的socket关闭steamFailed
在StreamAllocation中分析错误类型,判断是否还能在同一个connection上重试,如果不行,则标记noNewStream为true,并且deallocate connection,在connection没有allocations时,适当的释放掉socketnewStream
通过findHealthyConnection找到一个connection,寻找connection的过程中,先复用steamAllocation中存在的connection,或者去connectionPool中寻找,最后如果实在不行在生成一个新的connection,生成之后调用connection的connect方法
最后通过connection的newCodec生成一个HttpCodec
RetryAndFollowUpInterceptor
该类interceptor用于重试,以及follow redirect url。StreamAllocation在该interceptor中进行创建,并且传递给后面的interceptor。该interceptor最主要的处理在获取response过程中如果发生exception,则尝试recover,如果有follow的request,则继续发起请求,下面给出了核心代码
BridgeInterceptor
用于连接应用层和网络层,其中在OkHttpClient中配置的cookiejar会在该类中进行处理。
- intercept
在intercept过程中,给reqeust添加上”Content-Type”,”Content-Length”,”Host”,”Accept-Encoding”,”Cookie”等headers
同时在收到respond时,将cookie保存到CookieJar中。如果收到body经过了gzip的压缩,则自动解压
CacheInterceptor
中间通过InternalCache结构来控制网络respond缓存。http的缓存策略就是在这个interceptor中进行控制的
ConnectInterceptor
httpCodec和RealConnection是在这个interceptor中建立的,然后传递到chain的处理过程之中
httpCodec和connection最终通过streamAllocation的newStream进行创建,如果是TLS,还需要在这一步中和服务器进行握手
CallServerInterceptor
该Interceptor作为处理链中最后一层,主要任务即为通过httpCodec将request发送到服务器端,同时生成response
学习知识点
SSL/TLS简介
MD5,SHA1
AES,SHA1,DES,RSA,MD5区别
CloseGuard
okhttp库在RealCall的实现中,使用了CloseGuard来检查respond.body().close()方法是否显示被调用,具体CloseGuard的用法可以参考CloseGuard
第三方类库
- guava
Guava is a set of core libraries that includes new collection types (such as multimap and multiset), immutable collections, a graph library, functional types, an in-memory cache, and APIs/utilities for concurrency, I/O, hashing, primitives, reflection, string processing, and much more!