OkHttp探索之深入(基本概览)

前言:

     OkHttp 是 Android 经典的网络架构

工程比较大涉及知识点比较多,持续更新

相关
     Okhttp GitHub地址 https://github.com/square/okhttp
网络知识
     Http协议
     Http1.0
     Http1.1
     Http2.0
     Spdy
架构设计之设计模式
     外观模式
     责任链模式
     建造者模式
     观察者模式
     享元模式
     策略模式
池相关
     连接池
     线程池

网络连接的过程。
http://www.baidu.com 或者 https://www.baidu.com
主要流程图

20200707163658293.jpg

相关系列文章

[OKHttp探索之二(网络缓存)] (https://www.jianshu.com/p/efeae28dcb3e)

OkhttpClient 介绍 都包含哪些信息。

默认 两个网络协议 Protocol

public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
  static final List<Protocol> DEFAULT_PROTOCOLS = Util.immutableList(
      Protocol.HTTP_2, Protocol.HTTP_1_1);
    ................................................................
}

分别是
Protocol.HTTP_1_1 、 Protocol.HTTP_2
参考HTTP1.1 和 HTTP2.0的区别

默认 两个连接规则 ConnectionSpec

连接到尽可能多的主机。(连通性)

     想要连接更多服务器,得知道得多 (新的旧的都有) 所以要包含旧的TLS版本、以及设计不足的密码套件

连接的安全性。(安全性)

     想要 更安全性, 得要有最新 TLS版本和最强密码套件。

ConnectionSpec 用于 指定 传输HTTP流量的socket连接的配置
协商安全连接时的
1. TLS版本
2. 密码套件

 static final List<ConnectionSpec> DEFAULT_CONNECTION_SPECS = Util.immutableList(
      ConnectionSpec.MODERN_TLS, ConnectionSpec.CLEARTEXT);

具体的安全性与连接性决策由ConnectionSpec实现。OkHttp包括四个内置连接规格:
前两个是默认配置
MODERN_TLS   即 modern TLS 现代,最新的,时髦的,流行的,时新的TLS配置.
这样可以在大多数客户端平台上运行,并可连接到大多数服务器。
包含这2种版本(TLS 1.3、TLS 1.2)
要包含 被批准的、经过认可的密码套件

密码套件 ([cipher suites]
采用 approved_cipher_suites (被批准的经过认可的密码套件)

CLEARTEXT     URL的未加密、未经验证的连接 一般指 是用于http://开头的。
** ----------------------------------------------------------------------------------------------------**
RESTRICTED_TLS
A secure TLS connection that requires a recent client platform and a recent server.
一种受保护的连接 用于时间上最近用过的的客户端, 时间上最近的服务器。
包含这2种版本(TLS 1.3、TLS 1.2)
受限制的,保密的,未完全开放的密码套件

密码套件 ([cipher suites]
restricted_cipher_suites (受限制的,保密的,未完全开放的密码套件)

COMPATIBLE_TLS
一种向后兼容的回退配置,可在过时的客户端平台上工作,并且可以连接到过时的服务器。如果可能,请选择升级您的客户端平台或服务器而不是使用此配置。
包含这三种版本(TLS 1.3、TLS 1.2、 TLS 1.1、 TLS 1.0)
密码套件 ([cipher suites]
采用 approved_cipher_suites (被批准的经过认可的密码套件)
密码套件 常用的 RSA 和 ECDHE

RSA 是比较传统的密钥交换算法,它不具备前向安全的性质,因此现在很少服务器使用的。
ECDHE 算法具有前向安全,所以被广泛使用。

OkHttpClient有一个内部类的实现 Internal

一个抽象类,在OkHttpClient中静态代码块中初始化。

1.添加Header信息

2.确定连接池 ConnectionPool

3.equalsNonHost 检查两个Address是否是同可以复用

dns相同否,代理相同否。连接模式相同否,代理相同否等,锁定证书相同否,协议相同否,端口相同否、代理验证者等

4. code

responseBuilder.code

5. apply

ConnectionSpec tlsConfiguration tlsConfiguration.apply(sslSocket, isFallback);

6. Call newWebSocketCall(OkHttpClient client, Request originalRequest)

RealCall.newRealCall(client, originalRequest, true);

7. initExchange

responseBuilder.initExchange(exchange);

8. Exchange change

response.exchange;

中判断两个地址 Address
当  1、Connection 已经分配的数量超过分配限制
     2、被标记为不能再分配

则直接返回 false,

否则调用 equalsNonHost,
boolean equalsNonHost(Address that) {
    return this.dns.equals(that.dns)
        && this.proxyAuthenticator.equals(that.proxyAuthenticator)
        && this.protocols.equals(that.protocols)
        && this.connectionSpecs.equals(that.connectionSpecs)
        && this.proxySelector.equals(that.proxySelector)
        && equal(this.proxy, that.proxy)
        && equal(this.sslSocketFactory, that.sslSocketFactory)
        && equal(this.hostnameVerifier, that.hostnameVerifier)
        && equal(this.certificatePinner, that.certificatePinner)
        && this.url().port() == that.url().port();
}

OkHttpClient.Builder 外观模式加建造者模式

看看都包含什么 这几个即使OkHttpClient的成员变量, 也是建造者构造时所需的配置
有点多。

Dispatcher dispatcher;
    异步执行的调度策略
    最大请求数64个 maxRequests = 64;
    连接的最大请求数5个 maxRequestsPerHost = 5;
    异步请求准备队列

    Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();

    异步请求运行中队列

    Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();

    同步请求运行中队列

    Deque<RealCall> runningSyncCalls = new ArrayDeque<>();

    空闲时回调 Runnable idleCallback;
     ExecutorService executorService;

     线程池的执行者服务 主要用于调度线程的开启、关闭
这是OkHttp中默认创建的线程池执行者服务

     ExecutorService executorService = executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS, new SynchronousQueue<>(), Util.threadFactory("OkHttp Dispatcher", false));

     boolean isTerminated() 所有的任务都完成了,并且关闭啦
     shutdown() 关闭
     boolean awaitTermination() 处于阻塞状态,直到所有的任务完成,或者超时啦 , 又或者当前的线程发生中断
     invokeAll() 执行所有的任务
     invokeAny() 执行所有的
     execute() 执行线程池的任务

Proxy proxy;

两个属性
1.SocketAddress sa
2.Type type
代理的配置 Type有三种类型 direct、http、socks
direct代表直接连接
主要有两个方法
1.SocketAddress address()
2.Type type()

List<Protocol> protocols;

所用协议集合

List<ConnectionSpec> connectionSpecs;

连接规格 上面有提 TSL版本和密码套件

final List<Interceptor> interceptors = new ArrayList();

拦截器

final List<Interceptor> networkInterceptors = new ArrayList();

网络拦截器

EventListener.Factory eventListenerFactory;

事件的监听器, 用户调用Http时的监听, 数量,大小,时长等
callStart 调用的开始
dnsStart dns解析开始
dnsEnd dns解析结束
connectStart 连接的开始 socket connection
secureConnectStart 受保护的连接开始 TLS connection.
secureConnectEnd 连接TLS结束
connectEnd 连接结束 socket
connectFailed 连接失败
connectionAcquired 获取连接后调用
对于单个Call,可以多次调用该函数。例如,如果响应Call#request的是重定向到另一个地址
connectionReleased 连接释放后调用 connectionAcquired 在这个方法之后调用
对于单个Call,可以多次调用该函数。例如,如果响应到 Call#request的是重定向到另一个地址。
requestHeadersStart
requestHeadersEnd
requestBodyStart
requestBodyEnd
requestFailed
responseHeadersStart
responseHeadersEnd
responseBodyStart
responseBodyEnd
responseFailed
callEnd
callFailed

public interface Factory {
    EventListener create(Call call);
  }
ProxySelector proxySelector;

代理服务器是介于客户端和服务器之间的一台服务区
设置了代理服务器之后。客户端请求先被送到代理服务器,由代理服务器向真正的Web服务器发送请求
ProxySelector getDefault 获取默认代理服务
void setDefault 设置默认代理
List<Proxy> select(URI uri) 选择代理
void connectFailed(URI uri, SocketAddress sa, IOException ioe) 连接失败

CookieJar cookieJar;

既是一种策略 又时一种持久性存储
void saveFromResponse(HttpUrl url, List<Cookie> cookies);
List<Cookie> loadForRequest(HttpUrl url)

As policy, implementations of this interface are responsible for selecting which cookies to accept and which to reject.
作为策略,此接口的实现负责选择要接受和拒绝的cookie。
As persistence, implementations of this interface must also provide storage of cookies. Simple implementations may store cookies in memory; sophisticated ones may use the file system or database to hold accepted cookies.
作为持久性,该接口的实现还必须提供cookie的存储。简单的实现可以在内存中存储cookie;复杂的用户可以使用文件系统或数据库来保存接受的cookie。

Cache cache;

缓存的内容复杂 见另一篇 OkHttpCache
将HTTP和HTTPS响应缓存到文件系统,以便可以重用它们,从而节省时间和带宽。
InternalCache internalCache 内部缓存
DiskLruCache cache
writeSuccessCount;
writeAbortCount;
int networkCount;
int hitCount;
int requestCount;
Cache(File directory, long maxSize)
Cache(File directory, long maxSize, FileSystem fileSystem)
String key(HttpUrl url)
Response get(Request request)
CacheRequest put(Response response)
remove(Request request)
update(Response cached, Response network)
abortQuietly( DiskLruCache.Editor editor)
initialize() 初始化
delete()
evictAll()
Iterator<String> urls()
String next()
等等 见另一篇 OkHttpCache

InternalCache internalCache;

OkHttp的内部缓存接口。应用程序不应该实现这一点
Response get(Request request)
CacheRequest put(Response response)
remove(Request request) 删除所有的缓存
update(Response cached, Response network) 更新缓存
trackConditionalCacheHit() 跟踪一个满足缓存条件的GET请求
trackResponse(CacheStrategy cacheStrategy) 跟踪满足缓存策略CacheStrategy的响应

SocketFactory socketFactory;

此类创建套接字Socket。它可能被其他工厂子类化,这些工厂创建套接字的特定子类,从而为添加公共套接字级功能提供通用框架
单例 非双重锁
void setDefault(SocketFactory factory)
Socket createSocket()
SocketFactory getDefault()

SSLSocketFactory sslSocketFactory;

String getSecurityProperty(final String name) 安全的 财产
String [] getDefaultCipherSuites()
String [] getSupportedCipherSuites()
Socket createSocket(Socket s, String host,int port, boolean autoClose)
Socket createSocket(Socket s, InputStream consumed, boolean autoClose)

CertificateChainCleaner certificateChainCleaner;

证书链的清理器
List<Certificate> clean(List<Certificate> chain, String hostname)
CertificateChainCleaner get(X509TrustManager trustManager)
CertificateChainCleaner get(X509Certificate... caCerts)
X.509 是密码学里公钥证书的格式标准。
X.509证书里含有公钥、身份信息(比如网络主机名,组织的名称或个体名称等)和签名信息(可以是证书签发机构CA的签名,也可以是自签名)。

HostnameVerifier hostnameVerifier;

主机名验证的基本接口
在握手过程中,验证机制可以回调此接口的实现者,以确定是否应允许此连接

public boolean verify(String hostname, SSLSession session);
CertificatePinner certificatePinner;

锁定证书

约束受信任的证书。固定证书可防止对证书颁发机构的攻击。它还防止通过应用程序用户已知或未知的中间人证书颁发机构进行连接

锁定证书限制了服务器团队更新TLS证书的能力。通过锁定证书,可以增加操作复杂性,并限制在证书颁发机构之间迁移的能力。如果没有服务器的TLS管理员的许可,不要使用证书固定!

如果一个应用使用了Certificate Pinning技术,抓包工具 chales 和 fidder 就无法直接来调试/监控应用的网络流量的。

Authenticator proxyAuthenticator;

验证者 验证码 验证人 代理验证者

返回包含凭据的请求,以满足response中的身份验证质询。如果无法满足质询,则返回null。

路由是尽最大努力的,即使在逻辑上可用时,目前也可能不总是提供路由。当在应用程序拦截器中手动重新使用身份验证器时,例如在实现特定于客户端的重试时,也可能不提供身份验证器。

Authenticator authenticator;

验证者

ConnectionPool connectionPool;

连接池

Dns dns;

域名解析

boolean followSslRedirects;

跟随 ssl 重定向

boolean followRedirects;

跟随重定向

boolean retryOnConnectionFailure;

重新连接故障

int callTimeout;

调用超时

int connectTimeout;

连接超时

int readTimeout;

读取超时

int writeTimeout;

写入超时

int pingInterval;

Web套接字和HTTP/2 ping间隔(以毫秒为单位)。默认情况下,不会发送ping
此篇主要是OkHttp的门面类 OkHttpClient的概览。
其中包含了较多的相关类。 其中网络缓存篇 网络连接池篇逐一介绍。

RealConnectionPool

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,692评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,482评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,995评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,223评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,245评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,208评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,091评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,929评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,346评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,570评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,739评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,437评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,037评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,677评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,833评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,760评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,647评论 2 354

推荐阅读更多精彩内容

  • 前言 1. OkHttp 请求处理流程概述 当我们用 OkHttp 发起同步请求时,请求会被 OkHttp 的请求...
    灯不利多阅读 2,698评论 0 4
  • 前言 本系列主要分析OKHttp源代码的框架和设计思想,因为OKHttp实现了HTTP协议,所以在做源代码分析之前...
    嘎啦果安卓兽阅读 4,071评论 1 15
  • 本篇文章作为网络通信相关知识点的第三篇文章,大家在看这篇文章之前,可以先看前面的两篇文章,毕竟主要的知识点...
    Android开发_Hua阅读 331评论 0 1
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,714评论 2 59
  • 16宿命:用概率思维提高你的胜算 以前的我是风险厌恶者,不喜欢去冒险,但是人生放弃了冒险,也就放弃了无数的可能。 ...
    yichen大刀阅读 6,046评论 0 4