OKHttp3:4.12.0源码初探

672 阅读6分钟

okhttp 如何发起请求

fun main(){
    val okHttpClient = OkHttpClient().newBuilder()
        .connectTimeout(Duration.ofSeconds(10L))
        .readTimeout(Duration.ofSeconds(10L))
        .writeTimeout(Duration.ofSeconds(10L))
        .retryOnConnectionFailure(true)
        .build()

   val request = Request.Builder()
       .url("")
       .build()
    val newCall = okHttpClient.newCall(request)
    newCall.execute()
}

OkHttpClient.Builder

class Builder constructor() {
    //网络请求的调度器
  internal var dispatcher: Dispatcher = Dispatcher()
  //连接池
  internal var connectionPool: ConnectionPool = ConnectionPool()
  //应用拦截器
  internal val interceptors: MutableList<Interceptor> = mutableListOf()
  //网路拦截器
  internal val networkInterceptors: MutableList<Interceptor> = mutableListOf()
  //请求事件监听
  internal var eventListenerFactory: EventListener.Factory = EventListener.NONE.asFactory()
  //失败重试
  internal var retryOnConnectionFailure = true
  //服务器认证接口
  internal var authenticator: Authenticator = Authenticator.NONE
  //重定向
  internal var followRedirects = true
  //SSL重定向
  internal var followSslRedirects = true
  //Cookie
  internal var cookieJar: CookieJar = CookieJar.NO_COOKIES
  //网络缓存
  internal var cache: Cache? = null
  //DNS
  internal var dns: Dns = Dns.SYSTEM
  //代理
  internal var proxy: Proxy? = null
  internal var proxySelector: ProxySelector? = null
  internal var proxyAuthenticator: Authenticator = Authenticator.NONE
  //socket工厂
  internal var socketFactory: SocketFactory = SocketFactory.getDefault()
  //安全套接字
  //用于创建 SSL 套接字,配置 SSL/TLS 协议和加密套件
  internal var sslSocketFactoryOrNull: SSLSocketFactory? = null
  //用于验证服务器证书的有效性
  internal var x509TrustManagerOrNull: X509TrustManager? = null
  //用于定义客户端与服务器之间通信时使用的 TLS 版本和加密套件的配置类
  internal var connectionSpecs: List<ConnectionSpec> = DEFAULT_CONNECTION_SPECS
  //HTTP 协议
  internal var protocols: List<Protocol> = DEFAULT_PROTOCOLS
  //主机名称确认
  internal var hostnameVerifier: HostnameVerifier = OkHostnameVerifier
  //用于实现 **证书固定(Certificate Pinning)**  的类。
  //证书固定是一种安全机制,用于确保客户端只信任特定的服务器证书或公钥,从而防止中间人攻击
  internal var certificatePinner: CertificatePinner = CertificatePinner.DEFAULT
  internal var certificateChainCleaner: CertificateChainCleaner? = null
  
  internal var callTimeout = 0
  internal var connectTimeout = 10_000
  internal var readTimeout = 10_000
  internal var writeTimeout = 10_000
  internal var pingInterval = 0
  internal var minWebSocketMessageToCompress = RealWebSocket.DEFAULT_MINIMUM_DEFLATE_SIZE
  internal var routeDatabase: RouteDatabase? = null

Dispatcher

1.maxRequests 异步最大请求总数

@get:Synchronized var maxRequests = 64
  set(maxRequests) {
    require(maxRequests >= 1) { "max < 1: $maxRequests" }
    synchronized(this) {
      field = maxRequests
    }
    promoteAndExecute()
  }

2.maxRequestsPerHost 同一host下最大请求总数

@get:Synchronized var maxRequestsPerHost = 5
  set(maxRequestsPerHost) {
    require(maxRequestsPerHost >= 1) { "max < 1: $maxRequestsPerHost" }
    synchronized(this) {
      field = maxRequestsPerHost
    }
    promoteAndExecute()
  }

3.执行异步请求的线程池 核心线程0,允许的最大线程数MAX_VALUE

@get:JvmName("executorService") val executorService: ExecutorService
  get() {
    if (executorServiceOrNull == null) {
      executorServiceOrNull = ThreadPoolExecutor(0, Int.MAX_VALUE, 60, TimeUnit.SECONDS,
          SynchronousQueue(), threadFactory("$okHttpName Dispatcher", false))
    }
    return executorServiceOrNull!!
  }

4.readyAsyncCalls 异步请求等待队列

private val readyAsyncCalls = ArrayDeque<AsyncCall>()

5.runningAsyncCalls 进行中的异步请求队列

private val runningAsyncCalls = ArrayDeque<AsyncCall>()

6.runningSyncCalls 进行中的同步请求队列

private val runningSyncCalls = ArrayDeque<RealCall>()

1.同步请求

不受最大请求数限制,在当前线程执行

override fun execute(): Response {
    //防止重复请求
  check(executed.compareAndSet(false, true)) { "Already Executed" }
  callStart()
  try {
    //加入runningSyncCalls
    client.dispatcher.executed(this)
    //请求
    return getResponseWithInterceptorChain()
  } finally {
    client.dispatcher.finished(this)
  }
}

@Synchronized internal fun executed(call: RealCall) {
  runningSyncCalls.add(call)
}

2.异步请求

override fun enqueue(responseCallback: Callback) {
  check(executed.compareAndSet(false, true)) { "Already Executed" }

  callStart()
  //1创建AsyncCall,
  //2加入readyAsyncCalls,
  //3在readyAsyncCalls中寻找可执行的请求
  client.dispatcher.enqueue(AsyncCall(responseCallback))
}

internal fun enqueue(call: AsyncCall) {
  synchronized(this) {
    
    readyAsyncCalls.add(call)
    if (!call.call.forWebSocket) {
      //寻找同一host的异步请求
      val existingCall = findExistingCallWithHost(call.host)
      //同步同一host下asyncCall的数量
      if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)
    }
  }
  //寻找可执行的请求
  promoteAndExecute()
}

promoteAndExecute()

private fun promoteAndExecute(): Boolean {
  val executableCalls = mutableListOf<AsyncCall>()
  val isRunning: Boolean
  synchronized(this) {
    val i = readyAsyncCalls.iterator()
    while (i.hasNext()) {
      val asyncCall = i.next()
      //如果正在进行的异步请求总数大于最大请求(64),直接返回,等待下一个异步请求的完成
      if (runningAsyncCalls.size >= this.maxRequests) break 
      //如果指向同一host的请求总数大于最大同一host总数,继续从队列查找
      if (asyncCall.callsPerHost.get() >= this.maxRequestsPerHost) continue 
      i.remove()
      //找到可执行的异步请求,
      //host +1 
      asyncCall.callsPerHost.incrementAndGet()
      //加入可执行的集合
      executableCalls.add(asyncCall)
      //加入正在进行的异步队列
      runningAsyncCalls.add(asyncCall)
    }
    //
    isRunning = runningCallsCount() > 0
  }
  //执行符合条件的asyncCall  
  for (i in 0 until executableCalls.size) {
    val asyncCall = executableCalls[i]
    asyncCall.executeOn(executorService)
  }

  return isRunning
}

finished(call)

当一个请求完成时,promoteAndExecute会寻找可执行的请求

internal fun finished(call: AsyncCall) {
  call.callsPerHost.decrementAndGet()
  finished(runningAsyncCalls, call)
}

/** Used by [Call.execute] to signal completion. */
internal fun finished(call: RealCall) {
  finished(runningSyncCalls, call)
}

private fun <T> finished(calls: Deque<T>, call: T) {
  val idleCallback: Runnable?
  synchronized(this) {
    if (!calls.remove(call)) throw AssertionError("Call wasn't in-flight!")
    idleCallback = this.idleCallback
  }

  val isRunning = promoteAndExecute()

  if (!isRunning && idleCallback != null) {
    idleCallback.run()
  }
}

AsyncCall

RealCall下的内部类

fun executeOn(executorService: ExecutorService) {
  client.dispatcher.assertThreadDoesntHoldLock()

  var success = false
  try {
    executorService.execute(this)
    success = true
  } catch (e: RejectedExecutionException) {
    val ioException = InterruptedIOException("executor rejected")
    ioException.initCause(e)
    noMoreExchanges(ioException)
    responseCallback.onFailure(this@RealCall, ioException)
  } finally {
    if (!success) {
      client.dispatcher.finished(this) // This call is no longer running!
    }
  }
}
override fun run() {
    threadName("OkHttp ${redactedUrl()}") {
      var signalledCallback = false
      timeout.enter()
      try {
        val response = getResponseWithInterceptorChain()
        signalledCallback = true
        responseCallback.onResponse(this@RealCall, response)
      } catch (e: IOException) {
        if (signalledCallback) {
          // Do not signal the callback twice!
          Platform.get().log("Callback failure for ${toLoggableString()}", Platform.INFO, e)
        } else {
          responseCallback.onFailure(this@RealCall, e)
        }
      } catch (t: Throwable) {
        cancel()
        if (!signalledCallback) {
          val canceledException = IOException("canceled due to $t")
          canceledException.addSuppressed(t)
          responseCallback.onFailure(this@RealCall, canceledException)
        }
        throw t
      } finally {
        client.dispatcher.finished(this)
      }
    }
  }
}

RealInterceptorChain

getResponseWithInterceptorChain

okhttp主要是通过拦截器来完成整个网络请求过程,用户可以高度自定义拦截器来修改request,response

系统自定义的5个拦截器

  1. RetryAndFollowUpInterceptor:重试重定向
  2. BridgeInterceptor: 对用户的request进行修改添加header/cookie,对response进行gzip解压
  3. CacheInterceptor : 处理缓存
  4. ConnectInterceptor: 和服务器建立连接
  5. CallServerInterceptor:向服务器发送请求和接收服务器数据

request/interceptors生成一个RealInterceptorChain,来处理拦截器和接收数据

internal fun getResponseWithInterceptorChain(): Response {
  //
  val interceptors = mutableListOf<Interceptor>()
  //1.用户自定义的拦截器
  interceptors += client.interceptors
  //2.系统拦截器
  interceptors += RetryAndFollowUpInterceptor(client)
  interceptors += BridgeInterceptor(client.cookieJar)
  interceptors += CacheInterceptor(client.cache)
  interceptors += ConnectInterceptor
  if (!forWebSocket) {
     //3.网络拦截器
    interceptors += client.networkInterceptors
  }
  //4.系统拦截器
  interceptors += CallServerInterceptor(forWebSocket)

  val chain = RealInterceptorChain(
      call = this,
      interceptors = interceptors,
      index = 0,
      exchange = null,
      request = originalRequest,
      connectTimeoutMillis = client.connectTimeoutMillis,
      readTimeoutMillis = client.readTimeoutMillis,
      writeTimeoutMillis = client.writeTimeoutMillis
  )

  var calledNoMoreExchanges = false
  try {
    val response = chain.proceed(originalRequest)
    if (isCanceled()) {
      response.closeQuietly()
      throw IOException("Canceled")
    }
    return response
  } catch (e: IOException) {
    calledNoMoreExchanges = true
    throw noMoreExchanges(e) as Throwable
  } finally {
    if (!calledNoMoreExchanges) {
      noMoreExchanges(null)
    }
  }
}

client.interceptor和client.netWorkInterceptor区别

1.拦截器添加的位置不同,appInterceptor是在首位只会执行一次,networInterceptor在connectinterceptor和callserverIntercepter中间,当重试/重定向/服务器认证/连接池服用都会触发网络拦截器执行多次

2.应用拦截器修改的主要是用户定义的request 3.网络拦截器修改的主要是网络请求定义的request和response

拦截器执行的顺序,不包含重试重定向等

  1. 用户拦截器A
  2. 系统拦截器B
  3. 网络拦截器C
  4. 系统拦截器D :拿到服务器数据返回
  5. 网络拦截器C
  6. 系统拦截器B
  7. 用户拦截器A

拦截器

1.RetryAndFollowUpInterceptor

class RetryAndFollowUpInterceptor(private val client: OkHttpClient) : Interceptor {

  @Throws(IOException::class)
  override fun intercept(chain: Interceptor.Chain): Response {
    val realChain = chain as RealInterceptorChain
    var request = chain.request
    val call = realChain.call
    var followUpCount = 0
    var priorResponse: Response? = null
    var newExchangeFinder = true
    var recoveredFailures = listOf<IOException>()
    while (true) {
    //进入网络拦截器交换阶段
    //创建 exchangeFinder = ExchangeFinder()
      call.enterNetworkInterceptorExchange(request, newExchangeFinder)

      var response: Response
      var closeActiveExchange = true
      try {
        if (call.isCanceled()) {
          throw IOException("Canceled")
        }

        try {
        //执行请求
          response = realChain.proceed(request)
          newExchangeFinder = true
        } catch (e: RouteException) {
         //连接路由失败是否重试
          if (!recover(e.lastConnectException, call, request, requestSendStarted = false)) {
            throw e.firstConnectException.withSuppressed(recoveredFailures)
          } else {
            recoveredFailures += e.firstConnectException
          }
          newExchangeFinder = false
          continue
        } catch (e: IOException) {
          //服务器通信失败是否重试
          if (!recover(e, call, request, requestSendStarted = e !is ConnectionShutdownException)) {
            throw e.withSuppressed(recoveredFailures)
          } else {
            recoveredFailures += e
          }
          newExchangeFinder = false
          continue
        }

        //priorResponse!=null 说明已经执行过一个请求,得到过一个不可用的body的response
        if (priorResponse != null) {
          response = response.newBuilder()
              .priorResponse(priorResponse.newBuilder()
                  .body(null)
                  .build())
              .build()
        }
        //是否可以重定向
        val exchange = call.interceptorScopedExchange
        val followUp = followUpRequest(response, exchange)

        if (followUp == null) {
          if (exchange != null && exchange.isDuplex) {
            call.timeoutEarlyExit()
          }
          closeActiveExchange = false
          return response
        }
        //如果body只允许写入一次,直接返回
        val followUpBody = followUp.body
        if (followUpBody != null && followUpBody.isOneShot()) {
          closeActiveExchange = false
          return response
        }

        response.body?.closeQuietly()
        //超过最大重定向次数
        if (++followUpCount > MAX_FOLLOW_UPS) {
          throw ProtocolException("Too many follow-up requests: $followUpCount")
        }

        request = followUp
        priorResponse = response
      } finally {
        call.exitNetworkInterceptorExchange(closeActiveExchange)
      }
    }
  }
  
private fun followUpRequest(userResponse: Response, exchange: Exchange?): Request? {
  val route = exchange?.connection?.route()
  val responseCode = userResponse.code

  val method = userResponse.request.method
  when (responseCode) {
    HTTP_PROXY_AUTH -> {
      val selectedProxy = route!!.proxy
      if (selectedProxy.type() != Proxy.Type.HTTP) {
        throw ProtocolException("Received HTTP_PROXY_AUTH (407) code while not using proxy")
      }
      return client.proxyAuthenticator.authenticate(route, userResponse)
    }

    HTTP_UNAUTHORIZED -> return client.authenticator.authenticate(route, userResponse)

    HTTP_PERM_REDIRECT, HTTP_TEMP_REDIRECT, HTTP_MULT_CHOICE, HTTP_MOVED_PERM, HTTP_MOVED_TEMP, HTTP_SEE_OTHER -> {
      return buildRedirectRequest(userResponse, method)
    }

    HTTP_CLIENT_TIMEOUT -> {
      // 408's are rare in practice, but some servers like HAProxy use this response code. The
      // spec says that we may repeat the request without modifications. Modern browsers also
      // repeat the request (even non-idempotent ones.)
      if (!client.retryOnConnectionFailure) {
        // The application layer has directed us not to retry the request.
        return null
      }

      val requestBody = userResponse.request.body
      if (requestBody != null && requestBody.isOneShot()) {
        return null
      }
      val priorResponse = userResponse.priorResponse
      if (priorResponse != null && priorResponse.code == HTTP_CLIENT_TIMEOUT) {
        // We attempted to retry and got another timeout. Give up.
        return null
      }

      if (retryAfter(userResponse, 0) > 0) {
        return null
      }

      return userResponse.request
    }

    HTTP_UNAVAILABLE -> {
      val priorResponse = userResponse.priorResponse
      if (priorResponse != null && priorResponse.code == HTTP_UNAVAILABLE) {
        // We attempted to retry and got another timeout. Give up.
        return null
      }

      if (retryAfter(userResponse, Integer.MAX_VALUE) == 0) {
        // specifically received an instruction to retry without delay
        return userResponse.request
      }

      return null
    }

    HTTP_MISDIRECTED_REQUEST -> {
      // OkHttp can coalesce HTTP/2 connections even if the domain names are different. See
      // RealConnection.isEligible(). If we attempted this and the server returned HTTP 421, then
      // we can retry on a different connection.
      val requestBody = userResponse.request.body
      if (requestBody != null && requestBody.isOneShot()) {
        return null
      }

      if (exchange == null || !exchange.isCoalescedConnection) {
        return null
      }

      exchange.connection.noCoalescedConnections()
      return userResponse.request
    }

    else -> return null
  }
}
  

2.BridgeInterceptor

@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
  val userRequest = chain.request()
  //添加header
  val requestBuilder = userRequest.newBuilder()
    
  val body = userRequest.body
  if (body != null) {
    val contentType = body.contentType()
    if (contentType != null) {
      requestBuilder.header("Content-Type", contentType.toString())
    }

    val contentLength = body.contentLength()
    if (contentLength != -1L) {
      requestBuilder.header("Content-Length", contentLength.toString())
      requestBuilder.removeHeader("Transfer-Encoding")
    } else {
      requestBuilder.header("Transfer-Encoding", "chunked")
      requestBuilder.removeHeader("Content-Length")
    }
  }

  if (userRequest.header("Host") == null) {
    requestBuilder.header("Host", userRequest.url.toHostHeader())
  }

  if (userRequest.header("Connection") == null) {
    requestBuilder.header("Connection", "Keep-Alive")
  }

  // If we add an "Accept-Encoding: gzip" header field we're responsible for also decompressing
  // the transfer stream.
  var transparentGzip = false
  if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) {
    transparentGzip = true
    requestBuilder.header("Accept-Encoding", "gzip")
  }

  val cookies = cookieJar.loadForRequest(userRequest.url)
  if (cookies.isNotEmpty()) {
    requestBuilder.header("Cookie", cookieHeader(cookies))
  }

  if (userRequest.header("User-Agent") == null) {
    requestBuilder.header("User-Agent", userAgent)
  }

  val networkResponse = chain.proceed(requestBuilder.build())

  cookieJar.receiveHeaders(userRequest.url, networkResponse.headers)

  val responseBuilder = networkResponse.newBuilder()
      .request(userRequest)
   // gzip解压
  if (transparentGzip &&
      "gzip".equals(networkResponse.header("Content-Encoding"), ignoreCase = true) &&
      networkResponse.promisesBody()) {
    val responseBody = networkResponse.body
    if (responseBody != null) {
      val gzipSource = GzipSource(responseBody.source())
      val strippedHeaders = networkResponse.headers.newBuilder()
          .removeAll("Content-Encoding")
          .removeAll("Content-Length")
          .build()
      responseBuilder.headers(strippedHeaders)
      val contentType = networkResponse.header("Content-Type")
      responseBuilder.body(RealResponseBody(contentType, -1L, gzipSource.buffer()))
    }
  }

  return responseBuilder.build()
}

3.CacheInterceptor

@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
  val call = chain.call()
  //diskLruCache 存储缓存response
  val cacheCandidate = cache?.get(chain.request())

  val now = System.currentTimeMillis()
  //创建缓存策略
  //判断该缓存是否可用
  // 
  val strategy = CacheStrategy.Factory(now, chain.request(), cacheCandidate).compute()
  val networkRequest = strategy.networkRequest
  val cacheResponse = strategy.cacheResponse

  cache?.trackResponse(strategy)
  val listener = (call as? RealCall)?.eventListener ?: EventListener.NONE

  if (cacheCandidate != null && cacheResponse == null) {
    // The cache candidate wasn't applicable. Close it.
    cacheCandidate.body?.closeQuietly()
  }

  // If we're forbidden from using the network and the cache is insufficient, fail.
  if (networkRequest == null && cacheResponse == null) {
    return Response.Builder()
        .request(chain.request())
        .protocol(Protocol.HTTP_1_1)
        .code(HTTP_GATEWAY_TIMEOUT)
        .message("Unsatisfiable Request (only-if-cached)")
        .body(EMPTY_RESPONSE)
        .sentRequestAtMillis(-1L)
        .receivedResponseAtMillis(System.currentTimeMillis())
        .build().also {
          listener.satisfactionFailure(call, it)
        }
  }

  //禁止网络,返回缓存response
  if (networkRequest == null) {
    return cacheResponse!!.newBuilder()
        .cacheResponse(stripBody(cacheResponse))
        .build().also {
          listener.cacheHit(call, it)
        }
  }
    
  if (cacheResponse != null) {
    listener.cacheConditionalHit(call, cacheResponse)
  } else if (cache != null) {
    listener.cacheMiss(call)
  }

  var networkResponse: Response? = null
  try {
    networkResponse = chain.proceed(networkRequest)
  } finally {
    // If we're crashing on I/O or otherwise, don't leak the cache body.
    if (networkResponse == null && cacheCandidate != null) {
      cacheCandidate.body?.closeQuietly()
    }
  }

  // If we have a cache response too, then we're doing a conditional get.
  //服务器响应未修改,更新缓存响应
  if (cacheResponse != null) {
    if (networkResponse?.code == HTTP_NOT_MODIFIED) {
      val response = cacheResponse.newBuilder()
          .headers(combine(cacheResponse.headers, networkResponse.headers))
          .sentRequestAtMillis(networkResponse.sentRequestAtMillis)
          .receivedResponseAtMillis(networkResponse.receivedResponseAtMillis)
          .cacheResponse(stripBody(cacheResponse))
          .networkResponse(stripBody(networkResponse))
          .build()

      networkResponse.body!!.close()

      cache!!.trackConditionalCacheHit()
      //更新缓存
      cache.update(cacheResponse, response)
      return response.also {
        listener.cacheHit(call, it)
      }
    } else {
      cacheResponse.body?.closeQuietly()
    }
  }

  val response = networkResponse!!.newBuilder()
      .cacheResponse(stripBody(cacheResponse))
      .networkResponse(stripBody(networkResponse))
      .build()

  if (cache != null) {
    if (response.promisesBody() && CacheStrategy.isCacheable(response, networkRequest)) {
      //写入缓存
      val cacheRequest = cache.put(response)
      return cacheWritingResponse(cacheRequest, response).also {
        if (cacheResponse != null) {
          // This will log a conditional cache miss only.
          listener.cacheMiss(call)
        }
      }
    }

    if (HttpMethod.invalidatesCache(networkRequest.method)) {
      try {
        cache.remove(networkRequest)
      } catch (_: IOException) {
        // The cache cannot be written.
      }
    }
  }

  return response
}

4. ConnectInterceptor

负责建立连接

  1. 从currentCall,连接池中查找可用的连接,其中包括创建路由,dns解析,否则创建新连接
  2. 建立连接,创建socket,socket建立连接
  3. 建立TLS连接,完成TLS握手,加密,证书验证
object ConnectInterceptor : Interceptor {
  @Throws(IOException::class)
  override fun intercept(chain: Interceptor.Chain): Response {
    val realChain = chain as RealInterceptorChain
    //
    val exchange = realChain.call.initExchange(chain)
    val connectedChain = realChain.copy(exchange = exchange)
    return connectedChain.proceed(realChain.request)
  }
}

internal fun initExchange(chain: RealInterceptorChain): Exchange {
  //在retryAndFollowInterceptor中已经初始化  
  val exchangeFinder = this.exchangeFinder!!
  //寻找合适的ExchangeCode 来处理当前HTTP请求
  val codec = exchangeFinder.find(client, chain)
  val result = Exchange(this, eventListener, exchangeFinder, codec)
  this.interceptorScopedExchange = result
  this.exchange = result
  synchronized(this) {
    this.requestBodyOpen = true
    this.responseBodyOpen = true
  }

  if (canceled) throw IOException("Canceled")
  return result
}



ExchangeFinder
  1. 尝试从连接池中找到一个可复用的连接。
  2. 创建新连接: 如果没有可复用的连接,则创建一个新的连接。
  3. 验证连接: 确保连接是有效的(例如,未关闭、支持 HTTP/2 等)。
  4. 处理重定向和重试: 如果请求失败或需要重定向,则重新查找或创建连接。
  5. 返回 ExchangeCodec: 返回一个 ExchangeCodec 对象,用于执行实际的网络请求。
fun find(
  client: OkHttpClient,
  chain: RealInterceptorChain
): ExchangeCodec {
  try {
    val resultConnection = findHealthyConnection(
        connectTimeout = chain.connectTimeoutMillis,
        readTimeout = chain.readTimeoutMillis,
        writeTimeout = chain.writeTimeoutMillis,
        pingIntervalMillis = client.pingIntervalMillis,
        connectionRetryEnabled = client.retryOnConnectionFailure,
        doExtensiveHealthChecks = chain.request.method != "GET"
    )
    return resultConnection.newCodec(client, chain)
  } catch (e: RouteException) {
    trackFailure(e.lastConnectException)
    throw e
  } catch (e: IOException) {
    trackFailure(e)
    throw RouteException(e)
  }
}
@Throws(SocketException::class)
internal fun newCodec(client: OkHttpClient, chain: RealInterceptorChain): ExchangeCodec {
  val socket = this.socket!!
  val source = this.source!!
  val sink = this.sink!!
  val http2Connection = this.http2Connection

  return if (http2Connection != null) {
    Http2ExchangeCodec(client, this, chain, http2Connection)
  } else {
    socket.soTimeout = chain.readTimeoutMillis()
    source.timeout().timeout(chain.readTimeoutMillis.toLong(), MILLISECONDS)
    sink.timeout().timeout(chain.writeTimeoutMillis.toLong(), MILLISECONDS)
    Http1ExchangeCodec(client, this, source, sink)
  }
}
private fun findConnection(
  connectTimeout: Int,
  readTimeout: Int,
  writeTimeout: Int,
  pingIntervalMillis: Int,
  connectionRetryEnabled: Boolean
): RealConnection {
  if (call.isCanceled()) throw IOException("Canceled")

  //尝试服用当前的连接
  val callConnection = call.connection
  if (callConnection != null) {
    var toClose: Socket? = null
    synchronized(callConnection) {
    //检查当前的连接不可服用,被标记,端口主机不匹配,释放连接
      if (callConnection.noNewExchanges || !sameHostAndPort(callConnection.route().address.url)) {
        toClose = call.releaseConnectionNoEvents()
      }
    }
    //可复用的连接直接返回   
    if (call.connection != null) {
      check(toClose == null)
      return callConnection
    }
    toClose?.closeQuietly()
    eventListener.connectionReleased(call, callConnection)
  }
 
  //新的连接,需要的失败次数,重试次数   
  refusedStreamCount = 0
  connectionShutdownCount = 0
  otherFailureCount = 0

  //第一次尝试从连接池中获取可复用连接
  //快速查找,避免不必要的路由计算和连接创建
  //未指定具体的路由,仅根据目标地址匹配
  //主机地址/主机名/http2才可服用,
  if (connectionPool.callAcquirePooledConnection(address, call, null, false)) {
    val result = call.connection!!
    eventListener.connectionAcquired(call, result)
    return result
  }
   //路由创建计算和连接查找创建 
  // Nothing in the pool. Figure out what route we'll try next.
  val routes: List<Route>?
  val route: Route
  if (nextRouteToTry != null) {
    // Use a route from a preceding coalesced connection.
    routes = null
    route = nextRouteToTry!!
    nextRouteToTry = null
  } else if (routeSelection != null && routeSelection!!.hasNext()) {
    // Use a route from an existing route selection.
    routes = null
    route = routeSelection!!.next()
  } else {
    //创建路由选择器
    var localRouteSelector = routeSelector
    if (localRouteSelector == null) {
      localRouteSelector = RouteSelector(address, call.client.routeDatabase, call, eventListener)
      this.routeSelector = localRouteSelector
    }
    //addres,dns解析
     //返回可用路由列表   
    val localRouteSelection = localRouteSelector.next()
    routeSelection = localRouteSelection
    routes = localRouteSelection.routes

    if (call.isCanceled()) throw IOException("Canceled")

    //第二次从连接池中查找
    //携带路由列表,匹配连接池中的连接
    //比如dns解析后,多个ip地址匹配
    if (connectionPool.callAcquirePooledConnection(address, call, routes, false)) {
      val result = call.connection!!
      eventListener.connectionAcquired(call, result)
      return result
    }

    route = localRouteSelection.next()
  }

  //创建一个新的连接
  //connect建立连接
  val newConnection = RealConnection(connectionPool, route)
  call.connectionToCancel = newConnection
  try {
    newConnection.connect(
        connectTimeout,
        readTimeout,
        writeTimeout,
        pingIntervalMillis,
        connectionRetryEnabled,
        call,
        eventListener
    )
  } finally {
    call.connectionToCancel = null
  }
  //更新路由库
  call.client.routeDatabase.connected(newConnection.route())

  // If we raced another call connecting to this host, coalesce the connections. This makes for 3
  // different lookups in the connection pool!
  if (connectionPool.callAcquirePooledConnection(address, call, routes, true)) {
    val result = call.connection!!
    nextRouteToTry = route
    newConnection.socket().closeQuietly()
    eventListener.connectionAcquired(call, result)
    return result
  }

  synchronized(newConnection) {
    connectionPool.put(newConnection)
    call.acquireConnectionNoEvents(newConnection)
  }

  eventListener.connectionAcquired(call, newConnection)
  return newConnection
}

RealConnection

fun connect(
  connectTimeout: Int,
  readTimeout: Int,
  writeTimeout: Int,
  pingIntervalMillis: Int,
  connectionRetryEnabled: Boolean,
  call: Call,
  eventListener: EventListener
) {
 
  var routeException: RouteException? = null
  val connectionSpecs = route.address.connectionSpecs
  val connectionSpecSelector = ConnectionSpecSelector(connectionSpecs)
  //OKHttpClient默认系统的sslcocketFactory  
  if (route.address.sslSocketFactory == null) {
    if (ConnectionSpec.CLEARTEXT !in connectionSpecs) {
      throw RouteException(UnknownServiceException(
          "CLEARTEXT communication not enabled for client"))
    }
    val host = route.address.url.host
    if (!Platform.get().isCleartextTrafficPermitted(host)) {
      throw RouteException(UnknownServiceException(
          "CLEARTEXT communication to $host not permitted by network security policy"))
    }
  } else {
    if (Protocol.H2_PRIOR_KNOWLEDGE in route.address.protocols) {
      throw RouteException(UnknownServiceException(
          "H2_PRIOR_KNOWLEDGE cannot be used with HTTPS"))
    }
  }

  while (true) {
    try {
      //当前路由是否使用了代理服务器 
      //默认DIRECT直连
      if (route.requiresTunnel()) {
        //  
        connectTunnel(connectTimeout, readTimeout, writeTimeout, call, eventListener)
        if (rawSocket == null) {
          break
        }
      } else {
        //创建sslSocket,并建立连接  
        connectSocket(connectTimeout, readTimeout, call, eventListener)
      }
      //建立TLS连接
      establishProtocol(connectionSpecSelector, pingIntervalMillis, call, eventListener)
      eventListener.connectEnd(call, route.socketAddress, route.proxy, protocol)
      break
    } catch (e: IOException) {
      socket?.closeQuietly()
      rawSocket?.closeQuietly()
      socket = null
      rawSocket = null
      source = null
      sink = null
      handshake = null
      protocol = null
      http2Connection = null
      allocationLimit = 1

      eventListener.connectFailed(call, route.socketAddress, route.proxy, null, e)

      if (routeException == null) {
        routeException = RouteException(e)
      } else {
        routeException.addConnectException(e)
      }

      if (!connectionRetryEnabled || !connectionSpecSelector.connectionFailed(e)) {
        throw routeException
      }
    }
  }

  if (route.requiresTunnel() && rawSocket == null) {
    throw RouteException(ProtocolException(
        "Too many tunnel connections attempted: $MAX_TUNNEL_ATTEMPTS"))
  }

  idleAtNs = System.nanoTime()
}
@Throws(IOException::class)
private fun establishProtocol(
  connectionSpecSelector: ConnectionSpecSelector,
  pingIntervalMillis: Int,
  call: Call,
  eventListener: EventListener
) {
  
  eventListener.secureConnectStart(call)
  //**建立 TLS 连接**:在已经建立的 TCP 连接上,完成 TLS 握手,建立加密的 HTTPS 连接
  connectTls(connectionSpecSelector)
  eventListener.secureConnectEnd(call, handshake)
  //如果是http2协议  
  if (protocol === Protocol.HTTP_2) {
    //启动 HTTP/2,在
    startHttp2(pingIntervalMillis)
  }
}
private fun connectTls(connectionSpecSelector: ConnectionSpecSelector) {
  val address = route.address
  val sslSocketFactory = address.sslSocketFactory
  var success = false
  var sslSocket: SSLSocket? = null
  try {
    //创建sslSocket
    sslSocket = sslSocketFactory!!.createSocket(
        rawSocket, address.url.host, address.url.port, true /* autoClose */) as SSLSocket
    //设置加密套件,TLS版本
    //选择合适的 `ConnectionSpec`
    val connectionSpec = connectionSpecSelector.configureSecureSocket(sslSocket)
    //默认支持TLS扩展
    if (connectionSpec.supportsTlsExtensions) {
      Platform.get().configureTlsExtensions(sslSocket, address.url.host, address.protocols)
    }

    // 开始握手
    sslSocket.startHandshake()
    // block for session establishment
    val sslSocketSession = sslSocket.session
    val unverifiedHandshake = sslSocketSession.handshake()
    //证书验证
    // Verify that the socket's certificates are acceptable for the target host.
    if (!address.hostnameVerifier!!.verify(address.url.host, sslSocketSession)) {
      val peerCertificates = unverifiedHandshake.peerCertificates
      if (peerCertificates.isNotEmpty()) {
        val cert = peerCertificates[0] as X509Certificate
        throw SSLPeerUnverifiedException("""
            |Hostname ${address.url.host} not verified:
            |    certificate: ${CertificatePinner.pin(cert)}
            |    DN: ${cert.subjectDN.name}
            |    subjectAltNames: ${OkHostnameVerifier.allSubjectAltNames(cert)}
            """.trimMargin())
      } else {
        throw SSLPeerUnverifiedException(
            "Hostname ${address.url.host} not verified (no certificates)")
      }
    }

    val certificatePinner = address.certificatePinner!!
    handshake = Handshake(unverifiedHandshake.tlsVersion, unverifiedHandshake.cipherSuite,
        unverifiedHandshake.localCertificates) {
      certificatePinner.certificateChainCleaner!!.clean(unverifiedHandshake.peerCertificates,
          address.url.host)
    }

    // Check that the certificate pinner is satisfied by the certificates presented.
    certificatePinner.check(address.url.host) {
      handshake!!.peerCertificates.map { it as X509Certificate }
    }

    // 握手成功/记录TLS信息
    val maybeProtocol = if (connectionSpec.supportsTlsExtensions) {
      Platform.get().getSelectedProtocol(sslSocket)
    } else {
      null
    }
    socket = sslSocket
    //socket输入流
    source = sslSocket.source().buffer()
    //socket输出流
    sink = sslSocket.sink().buffer()
    protocol = if (maybeProtocol != null) Protocol.get(maybeProtocol) else Protocol.HTTP_1_1
    success = true
  } finally {
    if (sslSocket != null) {
      Platform.get().afterHandshake(sslSocket)
    }
    if (!success) {
      sslSocket?.closeQuietly()
    }
  }
}

5.CallServerInterceptor

主要功能

负责与服务器进行实际的网络通信

  1. 写入头信息
  2. 写入请求体
  3. 获取响应response
  4. 返回response
class CallServerInterceptor(private val forWebSocket: Boolean) : Interceptor {

  @Throws(IOException::class)
  override fun intercept(chain: Interceptor.Chain): Response {
    val realChain = chain as RealInterceptorChain
    //Http1ExchangeCodec /Http2ExchangeCodec
    val exchange = realChain.exchange!!
    val request = realChain.request
    val requestBody = request.body
    val sentRequestMillis = System.currentTimeMillis()

    var invokeStartEvent = true
    var responseBuilder: Response.Builder? = null
    var sendRequestException: IOException? = null
    try {
      //1.写入头信息 
      exchange.writeRequestHeaders(request)
      
      if (HttpMethod.permitsRequestBody(request.method) && requestBody != null) {
         //在发送请求体之前确认服务器是否愿意接收请求体 
        if ("100-continue".equals(request.header("Expect"), ignoreCase = true)) {
          exchange.flushRequest()
          //读取响应头信息
          responseBuilder = exchange.readResponseHeaders(expectContinue = true)
          exchange.responseHeadersStart()
          invokeStartEvent = false
        }
        if (responseBuilder == null) {
          //是否支持 双工通信,客户端和服务端同时发送和接收数据/http2/websocket 
          //默认不支持
          if (requestBody.isDuplex()) {
            exchange.flushRequest()
            val bufferedRequestBody = exchange.createRequestBody(request, true).buffer()
            requestBody.writeTo(bufferedRequestBody)
          } else {
            //2.写入请求体
            val bufferedRequestBody = exchange.createRequestBody(request, false).buffer()
            requestBody.writeTo(bufferedRequestBody)
            bufferedRequestBody.close()
          }
        } else {
          //没有请求体  
          exchange.noRequestBody()
          if (!exchange.connection.isMultiplexed) {
          //http1,连接不可被复用
          //noNewExchanges = true
            exchange.noNewExchangesOnConnection()
          }
        }
      } else {
        exchange.noRequestBody()
      }

      if (requestBody == null || !requestBody.isDuplex()) {
        exchange.finishRequest()
      }
    } catch (e: IOException) {
      if (e is ConnectionShutdownException) {
        throw e // No request was sent so there's no response to read.
      }
      if (!exchange.hasFailure) {
        throw e // Don't attempt to read the response; we failed to send the request.
      }
      sendRequestException = e
    }

    try {
      if (responseBuilder == null) {
        responseBuilder = exchange.readResponseHeaders(expectContinue = false)!!
        if (invokeStartEvent) {
          exchange.responseHeadersStart()
          invokeStartEvent = false
        }
      }
      
      //3.构建响应
      var response = responseBuilder
          .request(request)
          .handshake(exchange.connection.handshake())
          .sentRequestAtMillis(sentRequestMillis)
          .receivedResponseAtMillis(System.currentTimeMillis())
          .build()
      var code = response.code

      if (shouldIgnoreAndWaitForRealResponse(code)) {
        responseBuilder = exchange.readResponseHeaders(expectContinue = false)!!
        if (invokeStartEvent) {
          exchange.responseHeadersStart()
        }
        //4.构建带有响应体的response 
        response = responseBuilder
            .request(request)
            .handshake(exchange.connection.handshake())
            .sentRequestAtMillis(sentRequestMillis)
            .receivedResponseAtMillis(System.currentTimeMillis())
            .build()
        code = response.code
      }

      exchange.responseHeadersEnd(response)

      response = if (forWebSocket && code == 101) {
        // Connection is upgrading, but we need to ensure interceptors see a non-null response body.
        response.newBuilder()
            .body(EMPTY_RESPONSE)
            .build()
      } else {
        response.newBuilder()
            .body(exchange.openResponseBody(response))
            .build()
      }
      if ("close".equals(response.request.header("Connection"), ignoreCase = true) ||
          "close".equals(response.header("Connection"), ignoreCase = true)) {
        exchange.noNewExchangesOnConnection()
      }
      if ((code == 204 || code == 205) && response.body?.contentLength() ?: -1L > 0L) {
        throw ProtocolException(
            "HTTP $code had non-zero Content-Length: ${response.body?.contentLength()}")
      }
      return response
    } catch (e: IOException) {
      if (sendRequestException != null) {
        sendRequestException.addSuppressed(e)
        throw sendRequestException
      }
      throw e
    }
  }