第三方开源库OKHttp-整体架构和源码分析

news/2024/7/7 11:28:46

1. HTTP状态码

1xx: Infomational (信息状态码) ,接收的请求正在处理
2xx: Succeed(成功),请求正常处理完毕,如 200
3xx: Redirection(重定向),需要进行附加操作,一般是没有响应数据返回的,如 304(Not,modified)307 (重定向)
4xx: Client Error (客户端的错误),服务器无法处理请求,如 404
5xx: Server Error (服务端的错误),服务器处理请求出错,如 500

2.Http 和 Https 的区别:
Https = Http + 加密 + 验证 + 完整

端口:Http (80) Https (443)

Http 的缺点:
2.1 数据是没有加密传输,可能遭遇窃听
2.2 不验证通信方的身份,可能会遭遇伪装
2.3 无法验证报文的完整性,可能会遭遇篡改

TLS/SSL 协议
加密:对称加密(AES,DES) + 非对称加密 (RSA,DSA)
证书:要钱(便宜),建立连接的速度会拖慢,TCP 3 次握手,8 次握手

![对称加密.jpg

非对称加密.jpg

3. Http 1.x 和 Http 2.0 的区别
3.1 Http 2.0 采用二进制格式而非文本格式
3.2 Http 2.0 支持完全的多路复用
3.3 Http 2.0 使用报头压缩,降低开销
3.4 Http 2.0 让服务器将响应主动推送给客户端,(带内容推送,不带内容推送的通知)

Http1.0和Http2.0的区别.png

4. 异步和同步
跟线程没什么关系,打电话
同步:打电话 -> 处理(没挂断) -> 反馈
异步:打电话 -> 处理(挂断)-> 打回来

5. 整体架构和源码分析
5.1 自己如果要写一个框架你要怎么处理

  1. 网络是耗时,开线程,new Thread() ? 线程池
  2. 处理网络,HttpUrlConnection(简单) 或者 输入流+Socket(麻烦)
  3. 网络请求头信息处理,缓存的处理,文件格式上次的方式(表单提交,拼格式)
  4. 路由的一些操作,Http 2.0 复用 等等

5.2 OkHttp 大致内容 Okio,Socket
okio:原生的JavaIO + 自定义封装 ,其实就是对于 io 的封装

Socket 连接
拦截器

整体主线流程

  • 1、建造者模式构建okhttpClient
 mOkHttpClient = new OkHttpClient.Builder()
                            .cache(cache)
                            .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
                            .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
                            .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
                            .addInterceptor(mRewriteCacheControlInterceptor)
                            .addInterceptor(new LoggingInterceptor())
//                            .addInterceptor(interceptor)
//                            .cookieJar(new CookiesManager())
                            .cookieJar(cookieJar)
                            .build();

2、建造者模式构建Request

    Request.Builder requestBuilder = new Request.Builder();
        appendHeaders(requestBuilder);
        url = appendParams(url, mParams.urlParamsMap);
        return requestBuilder.get().url(url).tag(tag).build();
  • 3、newCall(不能重复执行)
    实际返回的是RealCall中的enqueue方法
    源码
  @Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }
  • 4、实际调用的Dispatcher.enqueue方法,而参数便是AsyncCall
  synchronized void enqueue(AsyncCall call) {
//如果正在运行队列的大小小于64并且主机允许的最大并发请求数量小于5则加入正在运行的异步请求中,否则加入等待异步队列中
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
      readyAsyncCalls.add(call);
    }
  }`
  • 5、异步执行任务AsyncCall中的execute方法
 executorService().execute(call);//call==AsyncCall
  • 6、返回结果
 @Override protected void execute() {
      boolean signalledCallback = false;
      try {
     //getResponseWithInterceptorChain责任链
        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);
      }
    }
  }

java几种线程池

  • 缓存线程池
Executors.newCachedThreadPool()

源码

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
  • 单线程池
  Executors.newSingleThreadExecutor()

源码

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));

OKHttp里面的线程池

  • enqueue源码分析:实际调用的是RealCall中的enqueue代码
  @Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }

dispatch中的enqueue方法

  synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
      readyAsyncCalls.add(call);
    }
  }

executorService()的源码

  public synchronized ExecutorService executorService() {
    if (executorService == null) {
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }

Util.threadFactory的源码分析

  public static ThreadFactory threadFactory(final String name, final boolean daemon) {
    return new ThreadFactory() {
      @Override public Thread newThread(Runnable runnable) {
        Thread result = new Thread(runnable, name);
        result.setDaemon(daemon);
        return result;
      }
    };
  }

分析结果:OkHttp里面的线程池采用的是缓存方案+线程工厂,而且不是守护线程

Okhttp源码阅读之责任链getResponseWithInterceptorChain

  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);
    return chain.proceed(originalRequest);
  }

image.png

源码分析.png

剩下的下一篇文章再分析


http://www.niftyadmin.cn/n/3648597.html

相关文章

严格遵循GPL的开放源码病毒现身

严格遵循GPL的开放源码病毒现身这种病毒在传播的过程中严格遵守GPL原则&#xff0c;会在感染机器的时候提供源代码和相关文档说明。由于这种病毒具有如此独特的特性&#xff0c;所以让防病毒机构也非常难办。大多数计算机用户对病毒恐怕都是又恨又怕。现在&#xff0c;大家又不…

如何在CentOS 8上安装Linux,Nginx,MySQL,PHP(LEMP)堆栈

介绍 (Introduction) The LEMP software stack is a group of software that can be used to serve dynamic web pages and web applications written in PHP. The name “LEMP” is an acronym that describes a Linux operating system with an Nginx (pronounced like “Eng…

App加密那点事浅浅析加密原理

本文章讲述利用cocos2d-x 开发手机游戏的一些加密心得。如有问题&#xff0c;请多指正。 更多信息详见&#xff1a;http://blog.csdn.net/chengyingzhilian/article/details/25540441 本文地址&#xff1a;http://blog.csdn.net/chengyingzhilian/article/details/38372601 好了…

外设资源共享须知

外设资源共享 具有相同ID的只能使用一个&#xff0c;无法同时使用。 例如当使能了SPIM0&#xff0c; 就不能用TWIM0&#xff0c;因为基地址相同&#xff0c;不能同时使用。此时建议使用TWIM1. 在sdk_config.h 中配置时需留意。

利用微软WebService技术实现远程数据库存取 利用web服务在不同站点间共享同一数据库

利用微软WebService技术实现远程数据库存取李凌宇 01-9-7 下午 01:18:14随着微软Visual Studo.Net Beta版的发布&#xff0c;由于Visual Studio.Net对XML以及Web服务的强大支持&#xff0c;利用Visual Studio.Net开发Web服务应用将会越来越多而且是非常的方便。本文以一个B2B电…

OKHttp源码精髓之拦截器分析

上一篇文章我们知道okhttp异步真正执行的实际是RealCall这个类的 getResponseWithInterceptorChain 方法 Response getResponseWithInterceptorChain() throws IOException {// 拦截器的一个集合List<Interceptor> interceptors new ArrayList<>();// 客户端的所…

如何在CentOS 7上安装Linux,Nginx,MySQL,PHP(LEMP)堆栈

介绍 (Introduction) A LEMP software stack is a group of open source software that is typically installed together to enable a server to host dynamic websites and web apps. This term is actually an acronym which represents the Linux operating system, with t…

AnnaKournikova病毒源代码解析

AnnaKournikova病毒源代码解析 AnnaKournikova病毒源代码解析 本帖版权归原作者&#xff0c;其它网站转载须注明出处&#xff0c;传统媒体转载须事先与原作者和e龙西祠胡同[http://www.xici.net]联系。 作者: hangsun 发表日期: 2001-03-10 16:41:08 返回《黑客也是侠》 快速返…