okhttp源码简单分析

首先来看okhttp的使用
// 网络请求客户端,同时还有上传下载文件,gzip压缩等功能
OkHttpClient client = new OkHttpClient()
// 构建请求
Request request = new Request.Builder().url(url).build();
// 同步请求
Response response = client.newCall(request).execute();
// 异步请求
client.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        e.printStackTrace();
    }
    @Override
    public void onResponse(Call call, Response response) throws IOException {
        if (!response.isSuccessful()) {
            if(callback != null) callback.onResonse(null);
            return;
        }
        callback.onResonse(response);
    }
});
1、首先看得到OkhttpClient,builder初始化一些设置
public Builder() {
  dispatcher = new Dispatcher();
  protocols = DEFAULT_PROTOCOLS;
  connectionSpecs = DEFAULT_CONNECTION_SPECS;
  proxySelector = ProxySelector.getDefault();
  cookieJar = CookieJar.NO_COOKIES;
  socketFactory = SocketFactory.getDefault();
  hostnameVerifier = OkHostnameVerifier.INSTANCE;
  certificatePinner = CertificatePinner.DEFAULT;
  proxyAuthenticator = Authenticator.NONE;
  authenticator = Authenticator.NONE;
  connectionPool = new ConnectionPool();
  dns = Dns.SYSTEM;
  followSslRedirects = true;
  followRedirects = true;
  retryOnConnectionFailure = true;
  connectTimeout = 10_000;
  readTimeout = 10_000;
  writeTimeout = 10_000;
}
2、调用newcall方法
@Override public Call newCall(Request request) {
  return new RealCall(this, request, false /* for web socket */);
}


/**
 * Uses {@code request} to connect a new web socket.
 */
@Override public WebSocket newWebSocket(Request request, WebSocketListener listener) {
  RealWebSocket webSocket = new RealWebSocket(request, listener, new SecureRandom());
  webSocket.connect(this);
  return webSocket;
}
可以看出支持WebSocket连接请求
3、excute方法回调
    void finished(RealCall call) {
        finished(runningSyncCalls, call, false);
    }


    private void finished(Deque calls, T call, boolean promoteCalls) {
        int runningCallsCount;
        Runnable idleCallback;
        synchronized (this) {
          if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
          if (promoteCalls) promoteCalls();
          runningCallsCount = runningCallsCount();
          idleCallback = this.idleCallback;
        }


        if (runningCallsCount == 0 && idleCallback != null) {
          idleCallback.run();
        }
    }
  在队列里取出call,然后执行run,源码如下
@Override protected void 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) {
      // Do not signal the callback twice!
      Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
    } else {
      responseCallback.onFailure(RealCall.this, e);
    }
  } finally {
    client.dispatcher().finished(this);
  }
}
4、连接和连接管理以及连接拦截器
  首先连接拦截器
  Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List 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);
    return chain.proceed(originalRequest);
  }
其中有重定向重试连接,缓存连接,缓存连接这里要说的是在连接缓存池中看是否有正在连接的连接。
RealConnection 连接类:
 1、最开始的连接,新建连接,新建连接需要首先查找一个合适的路径,然后在该路径上实例化一个新的connection对象
 2、从连接池中复用连接,其实就是从维护的队列中找到合适的连接并返回,查找的依据就是Address对象
public void connect(int connectTimeout, int readTimeout, int writeTimeout,
    List connectionSpecs, boolean connectionRetryEnabled) 
//https连接
/**
 * Does all the work to build an HTTPS connection over a proxy tunnel. The catch here is that a
 * proxy server can issue an auth challenge and then close the connection.
 */
private void buildTunneledConnection(int connectTimeout, int readTimeout, int writeTimeout,
    ConnectionSpecSelector connectionSpecSelector) throws IOException {


HTTPS是HTTP over SSL/TLS,HTTP是应用层协议,TCP是传输层协议,在应用层和传输层之间,增加了一个安全套接层SSL/TLS


ConnectionPool 连接池管理
public ConnectionPool() {this(5, 5, TimeUnit.MINUTES);}
双端队列deque,设置一个有最大五个连接,连接时长为5分钟的连接池,根据address来判断,如果,连接池中有这个长连接直接复用。

你可能感兴趣的:(okhttp源码简单分析)