okhttp源码分析

okhttp是square比较老的项目了,目前没多少人用了,可能大多数用square的retrofit替代了,不过retrofit的底层还是复用了okhttp的代码的。本文出于好奇分析下一次http请求从底到上的流程

基本流程

从最常见的demo开始吧,demo 从http://blog.csdn.net/lmj623565791/article/details/47911083 copy

//创建okHttpClient对象
OkHttpClient mOkHttpClient = new OkHttpClient();
//创建一个Request
final Request request = new Request.Builder()
                .url("https://github.com/hongyangAndroid")
                .build();
//new call
Call call = mOkHttpClient.newCall(request); 
//请求加入调度
call.enqueue(new Callback()
        {
            @Override
            public void onFailure(Request request, IOException e)
            {
            }

            @Override
            public void onResponse(final Response response) throws IOException
            {
                    //String htmlStr =  response.body().string();
            }
        });  
从newCall开始

  @Override public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
  }
可见子类是RealCall

  @Override public void enqueue(Callback responseCallback) {
    ...
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }
enqueue代码,注意传入的参数是个新建立的AsyncCall

 synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
      readyAsyncCalls.add(call);
    }
  }
executorService就是java标准的线程池,那么还是返回头来看call是什么

final class AsyncCall extends NamedRunnable {
    ...

    @Override protected void execute() {
      ...
        Response response = getResponseWithInterceptorChain();
      ...
       responseCallback.onResponse(RealCall.this, response);
      ...
    }
  }
getResponseWithInterceptorChain在同一个文件中,RealCall.java
  Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());
    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);
  }
可见这个是设计模式中的责任链模式,本文不关注其余的interceptor,只关注核心的ConnectInterceptor

  @Override public Response intercept(Chain chain) throws IOException {
    ...
    HttpCodec httpCodec = streamAllocation.newStream(client, chain, doExtensiveHealthChecks);
    RealConnection connection = streamAllocation.connection();

    return realChain.proceed(request, streamAllocation, httpCodec, connection);
  }
在它的处理方法中,建立了真正的数据连接

  public HttpCodec newStream(
      OkHttpClient client, Interceptor.Chain chain, boolean doExtensiveHealthChecks) {
      ...
      RealConnection resultConnection = findHealthyConnection(connectTimeout, readTimeout,
          writeTimeout, connectionRetryEnabled, doExtensiveHealthChecks);
      HttpCodec resultCodec = resultConnection.newCodec(client, chain, this);
      ...
  }
其中的resultCodec表示了http的协议版本,是http1,http2或者是其他协议。

  private RealConnection findHealthyConnection(int connectTimeout, int readTimeout,
      int writeTimeout, boolean connectionRetryEnabled, boolean doExtensiveHealthChecks)
      throws IOException {
    while (true) {
      RealConnection candidate = findConnection(connectTimeout, readTimeout, writeTimeout,
          connectionRetryEnabled);
      ...
      }
      ...
    }
  }
 private RealConnection findConnection(int connectTimeout, int readTimeout, int writeTimeout,
      boolean connectionRetryEnabled) throws IOException {
      ...
        result = new RealConnection(connectionPool, selectedRoute);
      ...

    // Do TCP + TLS handshakes. This is a blocking operation.
    result.connect(
        connectTimeout, readTimeout, writeTimeout, connectionRetryEnabled, call, eventListener);
    routeDatabase().connected(result.route());

    ...
    return result;
  }
findConnection实际上代码很长的,逻辑复杂,所贴代码是很简化的。简单的说就是建立新的Connection并连接。
public void connect(int connectTimeout, int readTimeout, int writeTimeout,
      boolean connectionRetryEnabled, Call call, EventListener eventListener) {
     ...
          connectSocket(connectTimeout, readTimeout, call, eventListener);
     ...
  }
依然是大幅度简化后的代码,建立socket连接

 private void connectSocket(int connectTimeout, int readTimeout, Call call,
      EventListener eventListener) throws IOException {
      ...
      Platform.get().connectSocket(rawSocket, route.socketAddress(), connectTimeout);
      ...
  }
使用平台相关代码做更近一步的工作,对于Android平台来说,代码在AndroidPlatform.java中

  @Override public void connectSocket(Socket socket, InetSocketAddress address,
      int connectTimeout) throws IOException {
      ...
      socket.connect(address, connectTimeout);
      ...
  }
这里的Socket就是java标准库中的java.net.Socket,后续调用到操作系统标准库,进而到内核等等和okhttp没啥关系了,okhttp的流程到此为止。

okhttp的功能

从上述的流程分析看,okhttp的流程没多复杂。但是它的作用不是体现在流程上的,它提供了多个完备的功能

从源码目录可以简单看出:

okhttp-master/okhttp/src/main/java/okhttp3/internal/cache
okhttp-master/okhttp/src/main/java/okhttp3/internal/cache2
okhttp-master/okhttp/src/main/java/okhttp3/internal/connection
okhttp-master/okhttp/src/main/java/okhttp3/internal/http
okhttp-master/okhttp/src/main/java/okhttp3/internal/http1
okhttp-master/okhttp/src/main/java/okhttp3/internal/http2
okhttp-master/okhttp/src/main/java/okhttp3/internal/io
okhttp-master/okhttp/src/main/java/okhttp3/internal/platform
okhttp-master/okhttp/src/main/java/okhttp3/internal/publicsuffix
okhttp-master/okhttp/src/main/java/okhttp3/internal/tls
okhttp-master/okhttp/src/main/java/okhttp3/internal/ws

1.缓存功能

2.输入输出Stream,物理Socket,逻辑连接,路由的管理

3.实现了http协议,包括http2和http1

4.优化的io功能,使用nio替代了io,优化了性能

5.多平台支持,对不同平台做不同差异化支持,默认的包括Android、jdk9和JdkWithJettyBootPlatform

6.安全层传输协议tls

7.websocket协议实现,rfc6455,是html5中的协议

除了主目录外还有

okhttp-master/okhttp-android-support  Android的支持,主要是io方面的改动
okhttp-master/okhttp-apache  apache接口兼容
okhttp-master/okhttp-logging-interceptor http日志相关
okhttp-master/okhttp-urlconnection java标准接口兼容

可以看出okhttp完全可以方便的替换HttpClient和HttpUrlConnection的使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值