美文网首页
okhttp源码系列-执行一次网络请求

okhttp源码系列-执行一次网络请求

作者: 头秃到底 | 来源:发表于2024-02-21 18:18 被阅读0次

    带着目的阅读源码,okhttp如何执行一次网络请求呢?
    本文通过samples.guide模块中的GetExample作为切入口。

    入口

    GetExample代码如下

    class GetExample {
    
      val client: OkHttpClient = OkHttpClient() // 创建okhttp客户端
    
      fun run(url: String): String? {
        val request: Request = Request.Builder() // 创建请求
            .url(url)
            .addHeader("User-Agent", "OkHttp Example")
            .build() // 通过链式+build模式创建一个网络请求
        return runCatching {
          client.newCall(request).execute().use { response -> // 同步获取网络响应
            if (!response.isSuccessful) {
              null
            } else {
              response.body?.string()
            }
          } 
        }.getOrNull()
      }
    }
    
    

    从上述代码可知执行一次网络请求需要如下步骤:

    • step 1:创建okhttp客户端client
    val client: OkHttpClient = OkHttpClient() // 创建okhttp客户端
    
    
    • step 2:创建网络请求并配置必要参数
    val request: Request = Request.Builder() // 创建请求
        .url(url)
        .addHeader("User-Agent", "OkHttp Example")
        .build() // 通过链式+build模式创建一个网络请求
    
    
    • step 3:执行网络请求并获取网络返回
    return runCatching {
      client.newCall(request).execute().use { response -> // 同步获取网络响应
        if (!response.isSuccessful) {
          null
        } else {
          response.body?.string()
        }
      }
    }.getOrNull()
    
    

    看上去是不是很简单,复杂的网络请求只需要三步即可完成,接下来我们带着问题逐步分析。

    什么是okhttp客户端

    OkHttp用途

    第一步中创建了OkHttpClient对象,注释中对其的定义为:

    Factory for calls, which can be used to send HTTP requests and read their responses.

    用于生成Call的工厂,Call可以发送并接收HTTP请求。Call是一个接口,代表一个可以执行的HTTP请求,如下:

    interface Call : Cloneable {
      fun request(): Request
    
      @Throws(IOException::class)
      fun execute(): Response
    
      fun enqueue(responseCallback: Callback)
    
      fun isExecuted(): Boolean
    
      fun isCanceled(): Boolean
    
      fun timeout(): Timeout
    
      public override fun clone(): Call
    
      fun interface Factory {
        fun newCall(request: Request): Call
      }
    }
    
    

    OkHttp的声明如下,除了可生成Call之外,还可生成一个WebSocket对象。

    open class OkHttpClient internal constructor(
      builder: Builder
    ) : Cloneable, Call.Factory, WebSocket.Factory
    
    

    WebSocket是一个WebSocket协议的操作接口,可利用它发送基于WebSocket协议的消息,WebSocket协议是基于TCP协议的可全双工通信的应用层网络协议,WebSocket接口如下:

    interface WebSocket {
      fun request(): Request
    
      fun queueSize(): Long
    
      fun send(text: String): Boolean
    
      fun send(bytes: ByteString): Boolean
    
      fun close(code: Int, reason: String?): Boolean
    
      fun cancel()
    
      fun interface Factory {
        fun newWebSocket(request: Request, listener: WebSocketListener): WebSocket
      }
    }
    
    

    总结一下:OkHttpClient主要用途是生成Call对象(处理HTTP请求),生成WebSocket对象(处理WebSocket请求)

    OkHttpClient属性

    OkHttpClient基于Builder建造者模式,可通过链式结构清晰地设置网络配置,具体的配置项及其相应功能如下:

    属性 功能
    dispatcher 调度器,设置执行异步请求的策略。
    connectionPool 设置可回收复用的HTTP/HTTPS的连接池,相同地址的HTTP请求可共享一个连接。
    interceptors 一个可修改的拦截器列表,该列表作用于建立连接之前到选择响应源的区间。
    networkInterceptors 一个可修改的网络拦截器列表,该列表作用于单个请求发起到响应的区间。
    eventListenerFactory 可监听到该客户端网络调用中各个阶段的情况
    retryOnConnectionFailure 设置此客户端在遇到连接问题时是否重试,默认为true,在一些特定情况下重试
    authenticator 当网络返回出现授权问题时,设置授权并重试。
    followRedirects 设置是否重定向。
    followSslRedirects 设置是否允许HTTP和HTTPS协议间的重定向,优先满足followRedirects。
    CookieJar 设置Cookie的保存和读取机制,默认是没有Cookie处理的。
    cache 设置网络响应缓存,可在无网环境时读取缓存数据。
    dns 设置DNS服务,用于查找host于ip地址的映射。
    proxy 设置代理,优先级高于proxySelector。
    proxySelector 设置proxy选择器,可根据不同的url设置不同的选择器,当[proxy]设置为null时可用,类似PAC和全局代理。有时可通过ProxySelector防止抓包,绕过代理
    proxyAuthenticator 设置代理服务器的授权,而authenticator是设置原始服务器的授权。
    socketFactory 用于创建连接的sockets对象。
    sslSocketFactory 用于创建HTPPS连接的SSLSocket对象。
    x509TrustManagerOrNull X509TrustManager主要用于校验HTTPS连接中服务端的证书,一般情况下无需设置,除非使用自签名证书或者不校验。
    connectionSpecs 主要用于指定HTTPS连接中可支持的TLS版本和密码套件。
    protocols 设置请求协议。
    hostnameVerifier 在握手期间,主要用于校验服务器的主机名是否与证书中的主机名相符,判断该连接是否有效。
    certificatePinner 通过设置合法的公钥,验证服务端证书的合法性,可以将你信任的服务器证书或公钥的散列值配置到你的客户端上,只有当服务器提供的证书或公钥的散列值与客户端配置的相匹配时,才认为这个连接是安全的。称作公钥锁定或证书固定
    certificateChainCleaner 用于移除不匹配的TSL链接并获取受信任的证书。
    callTimeout 设置一次完整请求(dns解析、连接、写入request、服务端处理、获取response;包括重定向和网络重试)的超时时间。
    connectTimeout 设置tcp连接(和target的tcp连接)的超时时间。
    readTimeout 设置服务器开始发送响应数据+客户端接收完响应数据的超时时间。
    writeTimeout 设置客户端开始发送请求数据+服务端接收完请求数据的超时时间。
    pingInterval 设置连续两次自动ping之间的时间间隔,使用此参数自动发送ping帧,直到连接失败或关闭。这将使连接保持活动状态,并可以检测到连接失败,在适用于长连接的场景。
    minWebSocketMessageToCompress 设置WebSocket消息需要压缩的最小大小,如果设置为1024,则WebSocket消息大于1024bytes后需要压缩,否则不压缩。
    routeDatabase OkHttp 的一个内部机制用于追踪和管理 HTTP 连接的路由信息,无法直接设置,可以通过connectionPool() 方法获取到连接池,并通过连接池来看到具体的路由信息

    什么是Request请求

    Request用途

    Request为一个HTTP请求,其包含了urlmethodheadersbody等网络所需配置。

    总结

    本章首先介绍如何用okhttp发送一个网络请求,然后分析OkhttpClient和Request的组成元素,后续看看okhttp是如何将请求发送出去的。

    相关文章

      网友评论

          本文标题:okhttp源码系列-执行一次网络请求

          本文链接:https://www.haomeiwen.com/subject/kjqwadtx.html