OKhttp
okhttp相关概念
网络七层模型 TCP五层模型
Tcp 三次握手 四次挥手
Tcp - ip协议
Socket
Http协议
Https
Dns解析
Okhttp源码相关概念
建造者 (自定义属性)
ReCall
分发器
拦截器
连接池
如何去进行网络请求的。
分发器 : 三个队列 和 线程池 。(数据结构 和 工作流程 ) (线程池的如何工作)
拦截器:责任链模式 (每个拦截器是 干什么的?)
连接池
网络相关概念
Tcp 五层模型 : 应用层(HTTP) 传输层(TCP,UDP) 网络层(IP) 数据链路层 物理地址层
OSI七层模式: 应用层分为 应用层 会话层 表示层
Tcp 三次握手:
客户端 发送一个请求申请 + 一个随机数 给 服务器
服务器 接收到 后 发送一个收到请求 + 随机数+1 给客户端
客户端 接受到 后 发送一个收到回复 + 随机数再加1 服务器 网络正式链接
Tcp 四次挥手
客户端 发送 结束的 申请 给服务器
服务器 发送 一个收到申请 和 一些必须发送数据 给 客户端 (客户端进入等待关闭状态)
服务器 再发送一个结束 给客户端
客户端 收到后 链接正式关闭
socket (数据传输方式)基于Tcp-ip协议 建立 socket 链接 ,通过socket来进行 数据传输。进程间的通讯(不同机器之间的通讯)
Http 协议: 请求头 请求空行 请求体 请求空行
响应头 响应空行 响应体
Https 是基于 http+ssl,加密,是对 tcp 三次握手的封装 ,连接时 通过 密钥和公钥 和三个随机数进行通信的
Dns 解析 :解析url地址 将域名 转化成ip地址 和相应 资源地址
Okhttp特点
支持HTTP/2 并允许对同一主机的所有请求共享一个套接字。(http1.0 无法对已经正在使用 的)
支持HTTP/2 则通过连接池,减少请求延迟。
默认请求 Gzip 压缩数据
响应缓存,避免了重复请求网络(强缓存,协商缓存)http协议定义
Okhttp流程
OkhttpClientBuild — OkhttpClient --Request—Call(RealCall)—execute 和enqueue方法------Dispatcher–Interceptor —Response
先通过建造者 构建相应网络请求的参数。得到OkhttpClient 。
Request 类 来确定 请求头信息。
OkhttpClient+Request 封装 Call (请求Call)
Call 调用 enqueue 和execute 进行同步或者异步请求
通过分发器 对任务进行 分发 线程分配
通过拦截器 对任务进行 网络请求
http请求过程是怎么样的?
- 域名----Dns解析 —获取 ip
- 建立tcp连接 (实质socket连接 得到socket对象)
- 用socket去发Http报文给服务器的到 Response(响应体)
分发器
重要 属性和类
Dispatcher
AsyncCall
runningAsyncCall
readyAsyncCall
runningSyncCall
线程池
异步请求工作流程
问题1:请求进来,如何解决将请求放入ready还是running队列
问题2:如何将ready队列放入running队列?
问题3:线程池是如何工作的?
源码解析:
一个RealCall只能 调用一次 enqueue方法
可以监听请求过曾(Dns解析 ,结束,开始连接)
分发器(new AsyncCall(回调接口))
Dispatcher 有三个队列
readyAsyncCalls runningAsyncCalls runningSyncCalls
数据结构:ArrayDeque (循环数组形成的双端队列)作为栈比Stack 快,作为双端队列比LinkedList快。
问题1 :请求进来 进行dns解析 全部 加入到 ready队列 ,然后再ready队列中一个一个取,当runningAsyncCalls个数小于64并且 callsPerHost同一域名的请求不大于5时,将该元素移至 running队列中。并添加到线程池中。
问题2:执行完一次任务的时候 ,将任务在running队列移除,然后再进行问题1的操作。
问题3:无等待,最大并发的。
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<>(), Util.threadFactory("OkHttp Dispatcher", false));
核心线程为0,最大线程为int的最大值 ,空闲事件为60s 阻塞队列为SynchronousQueue。所以时无等待最大并发。(通过三个队列来控制的。)
线程池的执行原理
线程进来 —先判断是否小于最大核心线程数—等于进入----阻塞队列 —是否满了—判断是否小于最大线程数—是---reject 拒绝策略。
除了阻塞队列 其他都会开线程。
SynchronousQueue ,ArrayBlockingQueue,LinkedBlockingQueue
ArrayBlockingQueue,LinkedBlockingQueue 数组和链表形成阻塞队列
SynchronousQueue 是无容量的阻塞队列。
阻塞队列满了 后 会判断是否小于最大线程数,小于的话会开一个新的线程。
SynchronousQueue 由于容量为0,所以会一直开。(从而达到高并发的效果)
拦截器责任链设计模式
重试重定向拦截器 重试重定向
桥接拦截器 请求头(必要的Host,gzip,contentType,cookies等)
缓存拦截器 缓存是否可用
连接拦截器 根据请求获取socket流
请求服务器拦截器 通过socket发送服务器得到response
自定义拦截器
请求前
网络请求前
socket代理
socks代理和http普通代理与隧道代理