Android框架源码分析——Okhttp源码分析

本文详细剖析OkHttpClient创建、请求构建、RealCall执行、调度器工作原理、拦截器机制等核心组件,揭示OkHttp高效网络请求的秘密。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、OkhttpClient创建

  • 创建OkhttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
  • OkHttpClient.Builder:配置并创建OkhttpClient
public Builder() {
  dispatcher = new Dispatcher(); //
  protocols = DEFAULT_PROTOCOLS; //默认支持的Http协议版本
  connectionSpecs = DEFAULT_CONNECTION_SPECS; //OKHttp连接(Connection)配置
  eventListenerFactory = EventListener.factory(EventListener.NONE); //Call状态监听器
  proxySelector = ProxySelector.getDefault(); //使用默认的代理选择器
  cookieJar = CookieJar.NO_COOKIES;//Cookie管理类,保存和添加Cookie,默认是没有Cookie的
  socketFactory = SocketFactory.getDefault(); //默认的Socket工厂产生Socket
  hostnameVerifier = OkHostnameVerifier.INSTANCE;
  certificatePinner = CertificatePinner.DEFAULT;
  proxyAuthenticator = Authenticator.NONE;
  authenticator = Authenticator.NONE;
  connectionPool = new ConnectionPool(); //连接池
  dns = Dns.SYSTEM;  //域名解析系统 domain name -> ip address;
  followSslRedirects = true;
  followRedirects = true;
  retryOnConnectionFailure = true;
  connectTimeout = 10_000;
  readTimeout = 10_000;
  writeTimeout = 10_000;
  pingInterval = 0;
}

总结OkHttpClient.Builder的配置如下:

  1. 创建默认任务调度器Dispatcher
  2. 创建Cookie管理类,保存和添加Cookie
  3. 默认的Socket工厂,产生Socket并连接使用
  4. 配置连接池ConnectionPool
  5. 配置重试、读写超时等

2、构建请求Request

  • 创建Request实例
Request request = new Request.Builder().url("").build();
  • 源码
public Builder() {  // 创建Builder
  this.method = "GET";
  this.headers = new Headers.Builder();  // 初始化Headers.Builder实例用于设置请求头
}
public Builder addHeader(String name, String value) {  // 设置请求头
  headers.add(name, value);
  return this;
}
public Builder url(String url) {   // 保存并设置URL
  if (url.regionMatches(true, 0, "ws:", 0, 3)) {
    url = "http:" + url.substring(3);
  } else if (url.regionMatches(true, 0, "wss:", 0, 4)) {
    url = "https:" + url.substring(4);
  }
  return url(HttpUrl.get(url));
}
public Request build() {   
  if (url == null) throw new IllegalStateException("url == null");
  return new Request(this);  // 将Builder拼接的信息保存在Request中
}
  • 代码执行的逻辑:
  1. 创建Request.Builder()对象,保存请求方法并初始化Headers.Builder对象
  2. 调用Builder的 url()和 addHeader()设置请求的地址和请求头Header
  3. 调用Builder的build()方法创建Request对象,将参数信息封装到Request中

3、RealCall执行网络请求

3.1、 execute:同步请求
@Override public Response execute() throws IOException {
  synchronized (this) {
    if (executed) throw new IllegalStateException("Already Executed”);//每个请求只能执行一次
    executed = true;
  }
  captureCallStackTrace();
  eventListener.callStart(this); // 开始请求状态回调
  try {
    client.dispatcher().executed(this);  //调用调度器dispatcher将RealCall加入正在执行的任务,
    Response result = getResponseWithInterceptorChain();  //执行网络请求并返回Response
    if (result == null) throw new IOException("Canceled");
    return result;
  } catch (IOException e) {
    eventListener.callFailed(this, e); // 请求失败回调
    throw e;
  } finally {
    client.dispatcher().finished(this);  //本次请求结束,继续执行未执行完成的异步任务
  }
}

总结execute执行过程:

  1. 首先判断当前Call实例是否执行过,每个请求只能执行一次
  2. execute()方法中首先根据监听listener回调网络请求状态开始
  3. 使用任务调度器执行Call,将此Call加入调度器的执行队列中,然后调用所有设置的拦截器依次执行,此方法也是Okhttp中的关键部分
  4. 在方法执行后调用任务调度器finished()方法结束此次任务,并继续是否有其他任务执行
  • getResponseWithInterceptorChain():使用拦截器策略处理网络请求
Response getResponseWithInterceptorChain() throws IOException {
  List<Interceptor> interceptors = new ArrayList<>();
  interceptors.addAll(client.interceptors()); // 添加Client中设置的拦截器
  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);
}

在getResponseWithInterceptorChain()执行:

  1. 创建Interceptor的集合,将用户设置的和连接所必须的Interceptor都添加到集合中
  2. 将Interceptor集合和配置参数封装到RealInterceptorChain中,此时index从0开始调用执行
  3. 依次调用chain.proceed(originalRequest),执行所有拦截器的interceptor,执行结束后获取并依次向上返回的Response,通过执行所有的interceptor完成整个网络请求
  • RealInterceptorChain
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
      RealConnection connection) throws IOException {
......
// 创建新的RealInterceptorChain实例,下标指向下一个Interceptor
    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
        connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
        writeTimeout);
    Interceptor interceptor = interceptors.get(index);  // 获取第一个执行的Interceptor
    Response response = interceptor.intercept(next);   //调用Interceptor的intercept()执行
    ......
    return response;
  }
}

Okhttp通过RealInterceptorChain类中的方法实现Interceptor的链式调用,这个地方可能会有疑问,如何把所有的Interceptor连接起来执行的,这里有点类似于递归的意思:

  1. getResponseWithInterceptorChain()中创建第一个RealInterceptorChain实例chain,此时传入index = 0 ,调用chain.proceed()
  2. 在chain的proceed()中又创建了index = 1的RealInterceptorChain实例next,并取出第一个拦截器执行intercept()
  3. 执行第一个拦截器的intercept(next),在intercept()中会调用传入next的proceed(),next实例的proceed()方法中,根据传入的index(此时为1)获取第二个拦截器,并创建第二个next2实例传入index = 2
  4. 执行第二个拦截器的intercept(next2),在拦截器的intercept()中会调用传入next2的proceed(),继续获取第三个拦截器并创建next3
  5. 。。。。。。。
  6. 直到拦截器结束,最后一个拦截器是CallServerInterceptor,它发起网络连接和请求并获的返回的Response
  7. 获取到Response后,倒数第二个拦截器继续执行结束,将Response回传到倒数第三个,依次向上回传直到,第一个拦截器
  8. 拦截器执行流程图:
    在这里插入图片描述
3.2、 enqueue:异步请求
@Override public void enqueue(Callback responseCallback) {
  synchronized (this) {
    if (executed) throw new IllegalStateException("Already Executed");
    executed = true;
  }
  captureCallStackTrace();
  eventListener.callStart(this); // 状态回调
  // 使用Callback创建AsyncCall,调用dispatcher调度器执行AsyncCall,先将AsyncCall加入异步执行队列然后依次执行任务
  client.dispatcher().enqueue(new AsyncCall(responseCallback)); 
}
@Override protected void execute() {  // AsyncCall中execute()
  boolean signalledCallback = false;
  try {
    Response response = getResponseWithInterceptorChain(); //执行拦截器
    if (retryAndFollowUpInterceptor.isCanceled()) {
      signalledCallback = true;
      responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
    } else {
      signalledCallback = true;
      responseCallback.onResponse(RealCall.this, response);
    }
  } catch (IOException e) {
    if (signalledCallback) {
    } else {
      eventListener.callFailed(RealCall.this, e);
      responseCallback.onFailure(RealCall.this, e);
    }
  } finally {
    client.dispatcher().finished(this); //执行结束,继续执行下一个任务
  }
}

总结:
1.异步执行时首先创建AsyncCall实例,并调用任务调度器执行AsyncCall
2. 调度器最终会执行到AsyncCall中的execute(),在execute()中和同步请求一样执行所有的拦截器

4、调度器:Dispatcher

  • 属性
private int maxRequests = 64;     // 默认支持最大的并发请求是64个
private int maxRequestsPerHost = 5;   //单个Host最多执行5个并发请求
/** 任务执行的线程池. */
private @Nullable ExecutorService executorService;
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
    new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
/** 待执行异步任务的队列*/
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
/** 正在执行异步任务的队列*/
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
/** 正在执行的同步任务的队列*/
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();

Dispatcher默认支持最大的并发请求是64个,单个Host最多执行5个并发请求,如果超过,则Call会先被放入到readyAsyncCall中,当出现空闲的线程时,再将readyAsyncCall中的线程移入到runningAsynCalls中执行请求,具体的属性见上面的注释;

  • executed / enqueue
synchronized void executed(RealCall call) { // 同步请求
  runningSyncCalls.add(call); // 添加到保存正在执行任务的队列中
}
synchronized void enqueue(AsyncCall call) { // 异步请求,根据现在请求数量是否超过限制去决定处理方式
  if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
    runningAsyncCalls.add(call);  // 添加到保存正在执行任务的队列中
    executorService().execute(call);   // 调用线程池执行execute()
  } else {
    readyAsyncCalls.add(call);   // 正在执行的任务达到上限时,添加到保存准备执行任务的队列中
  }
}

总结:

  1. 同步执行的直接将Call加入到同步队列runningSyncCalls中
  2. 异步请求的先判断当前请求的总数是否超过64,或当前host的请求是否超过5个,如果符合要求则调用线程池执行Call,并加入runningAsyncCalls队列
  3. 如果不满足上述条件,则将Call加入异步任务readyAsyncCalls等待执行
  4. 按照上面分析的Call的执行过程执行程序,执行结束后回调client.dispatcher().finished(this)
  • client.dispatcher().finished(this):请求结束都调用
void finished(AsyncCall call) { //异步请求结束
  finished(runningAsyncCalls, call, true);   // true
}
void finished(RealCall call) { //同步请求结束
  finished(runningSyncCalls, call, false);   // false
}
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
  int runningCallsCount;
  Runnable idleCallback;
  synchronized (this) {
    if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!); //首先移除执行完成的Call
    if (promoteCalls) promoteCalls();   // 如果是异步请求调用 promoteCalls()继续执行下一个Call
    runningCallsCount = runningCallsCount();
    idleCallback = this.idleCallback;
  }
  if (runningCallsCount == 0 && idleCallback != null) {
    idleCallback.run();
  }
}

在同步请求结束时,调用finish()将当前任务从队列中移除;在异步请求结束,调用finish()将当前任务从队列中移除,然后执行promoteCalls()继续执行ready中的Call

  • promoteCalls(): 从ready的集合中获取任务Call执行,知道满足执行任务的最大上限
private void promoteCalls() {
  if (runningAsyncCalls.size() >= maxRequests) return;  // 如果超多最大请求直接返回
  if (readyAsyncCalls.isEmpty()) return;   // 如果没有待执行任务 return
  for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
    AsyncCall call = i.next();    // 取出下一个任务
    if (runningCallsForHost(call) < maxRequestsPerHost) {
      i.remove();     // 移除队列中的任务
      runningAsyncCalls.add(call);    // 加人物加入正在执行的队列
      executorService().execute(call);    // 执行任务
    }
    if (runningAsyncCalls.size() >= maxRequests) return; 
  }
}

promoteCalls()执行:

  1. 首先判断正在执行的任务数量是否超过上限
  2. 判断ready中是否有要执行的任务Call
  3. 遍历取出ready队列中的任务执行并加入running队列中,直到符合最大上限
  • Dispatcher调度流程图
    在这里插入图片描述

5、拦截器Interceptor

5.1、RetryAndFollowUpInterceptor:重试拦截器

作为系统的第一个拦截器,按照前面拦截器的工作原理,此处最终获取到执行结果,如果执行结果失败后发起重试和重定向功能,那整个流程会再次发起请求;

while (true) {
  Response response = null;
  boolean releaseConnection = true; //将标识位设置true
  try { // (1)发起请求获取返回值
    response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);
    releaseConnection = false; //请求成功会设置flase
  } catch (RouteException e) {//捕获异常
    if (!recover(e.getLastConnectException(), false, request)) {//判断是否可以重试,否则抛出异常
      throw e.getLastConnectException();
    }
    releaseConnection = false;  //请求成功会设置flase
    continue; //跳过本次发起重试
  } catch (IOException e) {
    boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
    if (!recover(e, requestSendStarted, request)) throw e;
    releaseConnection = false;
    continue;
  } finally {
    if (releaseConnection) { //如果请求失败且不能重试,则关闭并释放资源
      streamAllocation.streamFailed(null);
      streamAllocation.release();
    }
  }
  • .recover()判断是否发起重试,具体判断情况见注释
//尝试从与服务器通信失败中恢复,如果可恢复返回true,否则返回false
private boolean recover(IOException e, boolean requestSendStarted, Request userRequest) {
  streamAllocation.streamFailed(e);
  // (1)okhttpClient配置时是否设置了禁止重试
  if (!client.retryOnConnectionFailure()) return false;
  // (2)不是上面捕获的异常,且请求的内容被 UnrepeatableRequestBody 标记,
  if (requestSendStarted && userRequest.body() instanceof UnrepeatableRequestBody) return false;
  // (3)异常是致命的
  if (!isRecoverable(e, requestSendStarted)) return false;
  // (4)没有尝试的路线了(调用RouteSelector.hasNext()判断是否有尝试路线)
  if (!streamAllocation.hasMoreRoutes()) return false;
  return true;
}
  1. 执行重定向,根据执行结果返回的状态码构建重新请求
Request followUp;
try {
  followUp = followUpRequest(response, streamAllocation.route()); // (1)根据错误的状态码,设置新的请求Request
} catch (IOException e) {
  streamAllocation.release();
  throw e;
}
if (followUp == null) { // 不需要重定向直接返回
  streamAllocation.release();
  return response;
}
if (++followUpCount > MAX_FOLLOW_UPS) { //(2)校验重试次数是否超过20次
  streamAllocation.release();
  throw new ProtocolException("Too many follow-up requests: " + followUpCount);
}
if (followUp.body() instanceof UnrepeatableRequestBody) { // 是否被UnrepeatableRequestBody包裹
  streamAllocation.release();
  throw new HttpRetryException("Cannot retry streamed HTTP body", response.code());
}
if (!sameConnection(response, followUp.url())) { // (3)比较重定向的Request和原来的是否一致,重定向后基本不会一样
  streamAllocation.release();
  streamAllocation = new StreamAllocation(client.connectionPool(),  //(4)重新创建StreamAllocation实例
      createAddress(followUp.url()), call, eventListener, callStackTrace);
  this.streamAllocation = streamAllocation;
} 
request = followUp;
priorResponse = response;
response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null); //(4)重新执行请求
  1. followUpRequest():根据请求返回的状态码,修改Request实现重定向再次发起请求
private Request followUpRequest(Response userResponse, Route route) throws IOException {
  int responseCode = userResponse.code();  //获取Response的响应码Code
  final String method = userResponse.request().method(); //获取请求方法method
  switch (responseCode) {
    case HTTP_PERM_REDIRECT:
    case HTTP_TEMP_REDIRECT:
      if (!method.equals("GET") && !method.equals("HEAD")) { //对于收到307、308的mehtod为GET和HEAD的不允许重定向
        return null;
      }
   
    case HTTP_MULT_CHOICE:
    case HTTP_MOVED_PERM:
    case HTTP_MOVED_TEMP:
    case HTTP_SEE_OTHER:
      if (!client.followRedirects()) return null; //判断客户端设置是否允许重定向
      String location = userResponse.header("Location”); // 
      if (location == null) return null;
      HttpUrl url = userResponse.request().url().resolve(location);
      return requestBuilder.url(url).build(); // 创建新的RequestBuilder
    case HTTP_CLIENT_TIMEOUT: //连接超时
      if (!client.retryOnConnectionFailure()) { //客户端设置是否循序重试
        return null;
      }
      
      if (userResponse.priorResponse() != null
          && userResponse.priorResponse().code() == HTTP_CLIENT_TIMEOUT) { //重试之后再次超时直接放弃重试
        return null;
      }
      return userResponse.request();
    case HTTP_UNAVAILABLE:
      if (userResponse.priorResponse() != null
          && userResponse.priorResponse().code() == HTTP_UNAVAILABLE) {  //重试之后还是 503 直接放弃
        return null;
      }
      if (retryAfter(userResponse, Integer.MAX_VALUE) == 0) {
        return userResponse.request();
      }
      return null;
    default:
      return null;
  }
}
 1. 407 代理未授权:在请求中添加 “Proxy-Authorization”
 2.  401 未授权:在请求中添加 “Authorization”
 3. 307308:如果不是 GET 或者 HEAD 请求不进行重定向
 4. 300301302303:均允许重定向
 5. 408: 客户端超时

RetryAndFollowUpInterceptor执行总结:

  1. RetryAndFollowUpInterceptor:作为系统的第一个拦截器,按照前面拦截器的工作原理,此处最终获取到执行结果,如果执行结果失败后发起重试和重定向功能,那整个流程会再次发起请求
  2. 当请求成功时直接返回Response,当请求异常时,判断是否满足或允许重定向和重试,不允许的直接返回Response结束请求
  3. 对满足重定向的执行followUpRequest()根据状态响应码修改Request,然后关闭之前的连接,重新创建并再次发起网络请求
5.1、 BridgeInterceptor:构建Request和响应信息
@Override public Response intercept(Chain chain) throws IOException {
  Request userRequest = chain.request();
  Request.Builder requestBuilder = userRequest.newBuilder();
  RequestBody body = userRequest.body();
  if (body != null) {
    MediaType contentType = body.contentType(); //(1)获取Body请求参数,将参数设置在请求头紫红
    if (contentType != null) {
      requestBuilder.header("Content-Type", contentType.toString());
    }
    long contentLength = body.contentLength(); //根据请求内容设置请求头的数据长度
    if (contentLength != -1) {
      requestBuilder.header("Content-Length", Long.toString(contentLength));
      requestBuilder.removeHeader("Transfer-Encoding");
    } else {
      requestBuilder.header("Transfer-Encoding", "chunked");
      requestBuilder.removeHeader("Content-Length");
    }
  }
  if (userRequest.header("Host") == null) { 
    requestBuilder.header("Host", hostHeader(userRequest.url(), false));2)设置请求主机Host
  }
  if (userRequest.header("Connection") == null) {
    requestBuilder.header("Connection", "Keep-Alive");
  }
  boolean transparentGzip = false;
  if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) {
    transparentGzip = true;  //设置请求数据压缩
    requestBuilder.header("Accept-Encoding", "gzip");
  }
  List<Cookie> cookies = cookieJar.loadForRequest(userRequest.url()); //根据请求地址获取请求的Cookies,此处在创建Client时掺入的CookieJar实例
  if (!cookies.isEmpty()) {
    requestBuilder.header("Cookie", cookieHeader(cookies));  // (3)查找、拼接所有的Cookie成字符串,设置请求头的Cookie
  }
  if (userRequest.header("User-Agent") == null) {
    requestBuilder.header("User-Agent", Version.userAgent());  //设置User-Agent
  }
  Response networkResponse = chain.proceed(requestBuilder.build()); //(4)传递下一个拦截器执行获取Response
  HttpHeaders.receiveHeaders(cookieJar, userRequest.url(), networkResponse.headers()); //更新保存的Cookie信息。调用设置的CookieJar更新Cookie
  Response.Builder responseBuilder = networkResponse.newBuilder()
      .request(userRequest);
  if (transparentGzip // 如果是采用了压缩请求,这里对数据进行解压
      && "gzip".equalsIgnoreCase(networkResponse.header("Content-Encoding"))
      && HttpHeaders.hasBody(networkResponse)) {
    GzipSource responseBody = new GzipSource(networkResponse.body().source());
    Headers strippedHeaders = networkResponse.headers().newBuilder()
        .removeAll("Content-Encoding")
        .removeAll("Content-Length")
        .build();
    responseBuilder.headers(strippedHeaders);
    responseBuilder.body(new RealResponseBody(strippedHeaders, Okio.buffer(responseBody)));//将请求的Response数据解压写入
  }
  return responseBuilder.build(); //返回Response
}

总结:

  1. 根据设置的Request请求补全并设置请求头信息,包含Cookie信息、数据压缩等
  2. 执行下一个拦截器并获取执行结果
  3. 根据执行结果更新Cookie信息
  4. 判读数据是否采用压缩,对压缩数据进行解压并返回
5.2、ConnectInterceptor:连接拦截器
@Override public Response intercept(Chain chain) throws IOException {
  RealInterceptorChain realChain = (RealInterceptorChain) chain;
  Request request = realChain.request();
  StreamAllocation streamAllocation = realChain.streamAllocation(); //(1)获取Retry中创建的StreamAllocation实例
 
  boolean doExtensiveHealthChecks = !request.method().equals("GET");
  HttpCodec httpCodec = streamAllocation.newStream(client, doExtensiveHealthChecks);
  RealConnection connection = streamAllocation.connection(); 
  return realChain.proceed(request, streamAllocation, httpCodec, connection);
}
  • StreamAllocation:实例创建在RetryAndFollowUpInterceptor拦截器中
//参数: 1、请求连接池 ;2、请求连接地址 ;3、请求任务栈
public StreamAllocation(ConnectionPool connectionPool, Address address, Object callStackTrace) {
  this.connectionPool = connectionPool; // 客户端初始化的连接池
  this.address = address;
  this.routeSelector = new RouteSelector(address, routeDatabase()); //创建RouteSelector实例
  this.callStackTrace = callStackTrace;
}
  • newStream():建立连接
public HttpCodec newStream(OkHttpClient client, boolean doExtensiveHealthChecks) {
  int connectTimeout = client.connectTimeoutMillis(); //获取设置的请求超时时间
  int readTimeout = client.readTimeoutMillis();
  int writeTimeout = client.writeTimeoutMillis();
  boolean connectionRetryEnabled = client.retryOnConnectionFailure(); //获取客户端设置的是否超时
  try {
    RealConnection resultConnection = findHealthyConnection(connectTimeout, readTimeout, writeTimeout, connectionRetryEnabled, doExtensiveHealthChecks);  // 获取正常的连接实例
    HttpCodec resultCodec = resultConnection.newCodec(client, this); //创建HttpCodec实例
    synchronized (connectionPool) {
      codec = resultCodec;
      return resultCodec;
    }
  } catch (IOException e) {
    throw new RouteException(e);
  }
}
//循环查找直到有健康的连接使用
private RealConnection findHealthyConnection(int connectTimeout, int readTimeout,
    int writeTimeout, boolean connectionRetryEnabled, boolean doExtensiveHealthChecks)
    throws IOException {
  while (true) {
    RealConnection candidate = findConnection(connectTimeout, readTimeout, writeTimeout, connectionRetryEnabled); // 查找连接
    synchronized (connectionPool) { // 如果此连接是全新的,不需要检查直接返回
      if (candidate.successCount == 0) {
        return candidate;
      }
    }
    if (!candidate.isHealthy(doExtensiveHealthChecks)) { //判断连接是否健康,否则从连接池移除,然后再次循环开始
      noNewStreams();
      continue;
    }
    return candidate;
  }
}
//返回承载新流的连接。如果存在连接,则优先选择现有连接,然后选择池,最后构建新连接
private RealConnection findConnection(int connectTimeout, int readTimeout, int writeTimeout,
    boolean connectionRetryEnabled) throws IOException {
  Route selectedRoute;
  synchronized (connectionPool) {
    RealConnection allocatedConnection = this.connection; //尝试使用已分配的连接
    if (allocatedConnection != null && !allocatedConnection.noNewStreams) {
      return allocatedConnection;
    }
  
    Internal.instance.get(connectionPool, address, this); //从连接池获取连接
    if (connection != null) {
      return connection;
    }
    selectedRoute = route;
  }
 
  if (selectedRoute == null) {
    selectedRoute = routeSelector.next(); //获取一条路线
  }
  RealConnection result;
  synchronized (connectionPool) {
    route = selectedRoute;
    refusedStreamCount = 0;
    result = new RealConnection(connectionPool, selectedRoute); //创建连接
    acquire(result);
  }
  result.connect(connectTimeout, readTimeout, writeTimeout, connectionRetryEnabled); //进行进行TCP+TLS握手,此时阻塞线程
  routeDatabase().connected(result.route());
  Socket socket = null;
  synchronized (connectionPool) {
    Internal.instance.put(connectionPool, result); //保存此连接到连接池
    if (result.isMultiplexed()) { //如果同时创建到同一地址的另一个多路复用连接,则释放该连接并获取该连接
      socket = Internal.instance.deduplicate(connectionPool, address, this);
      result = connection;
    }
  }
  closeQuietly(socket);
  return result;
}

从设置的连接池中查找合适的连接使用,如果没找到重新创建,创建连接RealConnection后执行三次握手和网络Socket的连接

5.3、CallServerInterceptor:写入请求报文并处理响应的Response
@Override public Response intercept(Chain chain) throws IOException {
  HttpCodec httpCodec = ((RealInterceptorChain) chain).httpStream(); //获取用于请求的Request、StreamAllocation、HttpCodec
  StreamAllocation streamAllocation = ((RealInterceptorChain) chain).streamAllocation();
  Request request = chain.request();
  long sentRequestMillis = System.currentTimeMillis();
  httpCodec.writeRequestHeaders(request); //(1)写入请求头
  Response.Builder responseBuilder = null;
  if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) { //判断是否有请求的方法体
    if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
      httpCodec.flushRequest();
      responseBuilder = httpCodec.readResponseHeaders(true);
    }
  
    if (responseBuilder == null) { //(2)写入请求体
      Sink requestBodyOut = httpCodec.createRequestBody(request, request.body().contentLength());
      BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
      request.body().writeTo(bufferedRequestBody);
      bufferedRequestBody.close();
    }
  }
  httpCodec.finishRequest();
  if (responseBuilder == null) {
    responseBuilder = httpCodec.readResponseHeaders(false); // (3)读取响应头信息
  }
  Response response = responseBuilder  // (4)构建返回的Response
      .request(request)
      .handshake(streamAllocation.connection().handshake())
      .sentRequestAtMillis(sentRequestMillis)
      .receivedResponseAtMillis(System.currentTimeMillis())
      .build();
  int code = response.code(); //获取响应码
  if (forWebSocket && code == 101) {
    response = response.newBuilder() //设置返回空的Response
        .body(Util.EMPTY_RESPONSE)
        .build();
  } else {
    response = response.newBuilder()   //构建返回的Response
        .body(httpCodec.openResponseBody(response))
        .build();
  }
    streamAllocation.noNewStreams(); //如果设置了close()关闭资源
  return response;
}

首先使用创建的httpCodec写入请求头、请求体,构建请求返回的Response并关闭资源;

OkhttpClient的执行流程分析就到此结束了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值