OkHttp源码流程简单分析

OkHttp原理流程源码分析 OkHttp已经是非常流行的android客户端的网络请求框架,我其实在项目中使用也已经好几年了,之前一直把重心放在如何快速的搞定业务上、迭代的效率上,这一点来讲,对于一个公司优秀员工是没有毛病的。但是越到后面,你会发现,真正的高效,是你对技术的更深层次的理解,对技术更熟练的掌握。所以今天重回技术本身,搞清楚OkHttp的实现机制和部分源码分析,也提醒阅读本篇文章的同学,除了在公司加班加点赶业务进度的同时,从长远角度看,提深自我的技术技能,才是对公司和自己的双赢结果。 “OkHttp 4.x upgrade 阅读详情

OkHttp用法

// 接入依赖
	implementation 'com.squareup.okhttp3:okhttp:3.8.0'
    implementation 'com.squareup.okio:okio:1.12.0'
	
// 基本用法
	
	// 创建OkHttpClient并设置拦截器、超时,是建造者模式
	val client = OkHttpClient.Builder()
            .addInterceptor {
                return@addInterceptor it.proceed(it.request())
            }
            .connectTimeout(60, TimeUnit.SECONDS)
            .build()
    
    // 创建请求对象,并设置请求头、方法、地址、body,是建造者模式        
    val request = Request.Builder()
            .addHeader("","")
            .post(RequestBody)
            .url("")
            .build()
    
    // 执行异步请求
    client.newCall(request).enqueue(object:Callback{
            override fun onFailure(call: Call, e: IOException) {
            }

            override fun onResponse(call: Call, response: Response) {
            }
    })

流程分析(以异步请求为例)

  • client.newCall(request).enqueue(Callback),开启一个异步网络请求,内部是执行一个client.dispatcher.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));
    }
    
  • client.dispatcher,我们可以暂且理解为线程池的工具类;内部维护了一个无核心线程且存活时长只有60s的线程;并且限定了默认最大的请求数是64,相同域名的最大请求数是5
    public final class Dispatcher {
      // 最大请求并发数
      private int maxRequests = 64;
      // 相同域名的最大并发数
      private int maxRequestsPerHost = 5;
      private @Nullable ExecutorService executorService;
    
      public Dispatcher(ExecutorService executorService) {
        this.executorService = executorService;
      }
    
      public Dispatcher() {
      }
    
      // 创建线程池
      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;
      }
    }
    
  • client.dispatcher.enqueue(AsyncCall),在其内部主要是对请求任务的分派到线程池中执行/等待执行
    synchronized void enqueue(AsyncCall call) {
    	// 注释1:校验并发请求数量
        if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
          runningAsyncCalls.add(call);
          // 注释2:将请求任务添加到线程池中
          executorService().execute(call);
        } else {
          readyAsyncCalls.add(call);
        }
    }
    
  • AsyncCall.execute(),AsyncCall是Runnable子类,当线程池运行后,会执行其exectue(),在其内部主要是干了一件大事,就是按顺序执行了拦截器,执行拦截器是通过责任链式的设计模式,等待所有拦截器执行完毕后,会通过Callback将执行的结果回调给用户
    @Override protected void execute() {
      boolean signalledCallback = false;
      try {
     	// 注释1:执行拦截器,并接收拦截器对下发响应的处理
        Response response = getResponseWithInterceptorChain();
        if (retryAndFollowUpInterceptor.isCanceled()) {
          signalledCallback = true;
          // 注释2:请求失败
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          signalledCallback = true;
          // 注释3:请求成功
          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);
      }
    }
    
  • getResponseWithInterceptorChain(),内部就是先整理我们自定义的拦截器,然后是RetryAndFollowUpInterceptor重试/重定向拦截器、BirdgeInterceptor桥接拦截器、CacheInterceptor缓存拦截器、ConnectInterceptor连接拦截器、CallServerInterceptor服务回调拦截器;其内部的玩法主要是通过创建RealInterceptorChain对象,并且持有待执行的拦截器所在的索引,然后通过chain.proceed(request),在其内部会再次创建一个RealInterceptorChain对象,并持有下一个待执行的拦截器索引,然后执行当前拦截器的intercept(chain)并返回chain.proceed(request)即类似递归效应,直至所有拦截器全部执行完毕
    Response getResponseWithInterceptorChain() throws IOException {
    	// 注释1:整理拦截器,并按顺序执行
        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));
    
    	// 注释2:创建RealInterceptorChain,并执行proceed
        Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0, originalRequest);
        return chain.proceed(originalRequest);
    }
    
    // 注释3:内部创建RealInterceptorChain并持有下一个拦截器的引用
    public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,RealConnection connection) throws IOException {
        if (index >= interceptors.size()) throw new AssertionError();
        ...
        // 注释4:创建RealInterceptorChain,并获取到下一个拦截器所在的索引,待取出下一个拦截器进行执行
        RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec, connection, index + 1, request);
        Interceptor interceptor = interceptors.get(index);
        Response response = interceptor.intercept(next);
    	...
        return response;
    }
    
    考点:责任链式模式的优点?更大程度上实现功能性的解藕,当删除链上的任意节点,对整个链的运行不受影响
  • RetryAndFollowUpInterceptor:重试/重定向拦截器;作用是对于后面拦截器执行出现的异常如:路由异常、服务连接异常等会进行重新尝试运行后面拦截器;如果是返回了需要重定向的code,则会进行url的重新拼装,重新尝试执行后面拦截器,但是重定向是有次数限制的,不超过20次
  • BirdgeInterceptor:桥接拦截器;作用是对报文数据的处理,如:请求头的拼接、报文的压缩、以及对下发的Response的解压等操作
  • CacheInterceptor:缓存拦截器;作用就是当条件符合的情况下,从缓存中取数据,如:当支持缓存的情况下,无网络,且有缓存,则取缓存中的数据、当下发的code是304,表示未被修改的,则取的是缓存中的,可能会对响应头的数据刷新缓存、还有就是对于,数据的修改得到的响应是不做缓存处理的,如:post、put、delete等请求
  • ConnectInterceptor:连接拦截器;作用就是获取一个可以用于连接的服务器的链接,先是从链接池中寻找一个可用的链接,通过遍历链接池,与在目标请求地址做匹配,当域名和端口一致时,就可以复用该链接;如果没有找到可用的链接时,则创建一个新的链接RealConnect,然后通过socket开启链接主机,并将新的链接保存到链接池中
    private RealConnection findConnection(int connectTimeout, int readTimeout, int writeTimeout,
      boolean connectionRetryEnabled) throws IOException {
        Route selectedRoute;
        synchronized (connectionPool) {
        	...
          // 注释1:从链接池中遍历,找到合适的链接
          Internal.instance.get(connectionPool, address, this, null);
          if (connection != null) {
            return connection;
          }
        }
    	...
    	// 注释2:链接池中没有可以用的链接,则创建一个链接
    	result = new RealConnection(connectionPool, selectedRoute);
        ...
        // 注释3:建立链接,通过socket
        result.connect(connectTimeout, readTimeout, writeTimeout, connectionRetryEnabled);
        routeDatabase().connected(result.route());
    
        Socket socket = null;
        synchronized (connectionPool) {
          // 注释4:添加到链接池中,并且会开启一个线程池任务监听每个链接的空闲状态,是否需要被清理
          Internal.instance.put(connectionPool, result);
          if (result.isMultiplexed()) {
            socket = Internal.instance.deduplicate(connectionPool, address, this);
            result = connection;
          }
        }
        closeQuietly(socket);
        return result;
    }
    
    // 从链接池中找一个可用的链接
    @Nullable RealConnection get(Address address, StreamAllocation streamAllocation, Route route) {
        assert (Thread.holdsLock(this));
        for (RealConnection connection : connections) {
    	  // 匹配域名和端口一致的链接
          if (connection.isEligible(address, route)) {
            streamAllocation.acquire(connection);
            return connection;
          }
        }
        return null;
    }
    
    public boolean isEligible(Address address, @Nullable Route route) {
        // 校验当前是否允许再创建链接流
        if (allocations.size() >= allocationLimit || noNewStreams) return false;
    
        // 域名跟端口一致的链接,即为可用
        if (!Internal.instance.equalsNonHost(this.route.address(), address)) return false;
        if (address.url().host().equals(this.route().address().url().host())) {
          return true; // This connection is a perfect match.
        }
    
    	// 下面的匹配不太清楚
        // At this point we don't have a hostname match. But we still be able to carry the request if
        // our connection coalescing requirements are met. See also:
        // https://hpbn.co/optimizing-application-delivery/#eliminate-domain-sharding
        // https://daniel.haxx.se/blog/2016/08/18/http2-connection-coalescing/
    
        // 1. This connection must be HTTP/2.
        if (http2Connection == null) return false;
    
        // 2. The routes must share an IP address. This requires us to have a DNS address for both
        // hosts, which only happens after route planning. We can't coalesce connections that use a
        // proxy, since proxies don't tell us the origin server's IP address.
        if (route == null) return false;
        if (route.proxy().type() != Proxy.Type.DIRECT) return false;
        if (this.route.proxy().type() != Proxy.Type.DIRECT) return false;
        if (!this.route.socketAddress().equals(route.socketAddress())) return false;
    
        // 3. This connection's server certificate's must cover the new host.
        if (route.address().hostnameVerifier() != OkHostnameVerifier.INSTANCE) return false;
        if (!supportsUrl(address.url())) return false;
    
        // 4. Certificate pinning must match the host.
        try {
          address.certificatePinner().check(address.url().host(), handshake().peerCertificates());
        } catch (SSLPeerUnverifiedException e) {
          return false;
        }
    
        return true; // The caller's address can be carried by this connection.
    }
    
  • Internal.instance.put(connectionPool, result);:将新建的链接添加到链接池中,并且会在需要的时候开启任务去监听链接池中链接的空闲状态是否需要被清理,具体如何清理超时的空闲流程,代码注释中已表明清楚
    void put(RealConnection connection) {
        assert (Thread.holdsLock(this));
        if (!cleanupRunning) {
          cleanupRunning = true;
          // 注释1:将清理任务添加到线程池中
          executor.execute(cleanupRunnable);
        }
        // 注释2:将链接添加到链接池中
        connections.add(connection);
    }
    
    private final Runnable cleanupRunnable = new Runnable() {
    @Override public void run() {
      while (true) {
      	// 注释3:检查每个链接是否超时,并从链接池中清理,以及关闭链接socket
        long waitNanos = cleanup(System.nanoTime());
        // 注释4:当链接池中无链接时,退出监听任务
        if (waitNanos == -1) return;
        if (waitNanos > 0) {
          long waitMillis = waitNanos / 1000000L;
          waitNanos -= (waitMillis * 1000000L);
          synchronized (ConnectionPool.this) {
            try {
              // 注释4:等待即将要超时的链接,然后重新去检查,并处理超时的链接
              ConnectionPool.this.wait(waitMillis, (int) waitNanos);
            } catch (InterruptedException ignored) {
            }
          }
        }
      }
    }
    };
    
    long cleanup(long now) {
        int inUseConnectionCount = 0;
        int idleConnectionCount = 0;
        RealConnection longestIdleConnection = null;
        long longestIdleDurationNs = Long.MIN_VALUE;
        synchronized (this) {
          for (Iterator<RealConnection> i = connections.iterator(); i.hasNext(); ) {
            RealConnection connection = i.next();
            // 注释5:判断当前链接是否处于空闲,并计算当前的的空闲时长
            if (pruneAndGetAllocationCount(connection, now) > 0) {
              inUseConnectionCount++;
              continue;
            }
            // 注释6:空闲链接计数器
            idleConnectionCount++;
            
            long idleDurationNs = now - connection.idleAtNanos;
            if (idleDurationNs > longestIdleDurationNs) {
              longestIdleDurationNs = idleDurationNs;
              longestIdleConnection = connection;
            }
          }
    
    	  // 注释7:判断当前链接已经超时,直接移除链接池
          if (longestIdleDurationNs >= this.keepAliveDurationNs
              || idleConnectionCount > this.maxIdleConnections) {
            connections.remove(longestIdleConnection);
            
            // 注释8:存在空闲链接,但是还未超时,则返回一个剩余时长
          } else if (idleConnectionCount > 0) {
            return keepAliveDurationNs - longestIdleDurationNs;
    		
    		// 注释9:正在使用的链接,返回他的时长为5分钟
          } else if (inUseConnectionCount > 0) {
            return keepAliveDurationNs;
    		
    		// 注释10:表示此时链接池已无链接,返回-1,即将关闭监听任务
          } else {
            cleanupRunning = false;
            return -1;
          }
        }
        // 注释11:对已经超时的链接进行关闭
        closeQuietly(longestIdleConnection.socket());
        return 0;
    }
    
  • CallServerInterceptor:回调服务拦截器:作用就是通过ConnectInterceptor建立的链接得到的流,进行与服务器的通信,发送requestBody,以及等待Response的响应,然后将从流中读取到的数据转化,并构建出Response往上面的拦截器发送,交由他们处理,最终回到用户端
    public final class CallServerInterceptor implements Interceptor {
      private final boolean forWebSocket;
    
      @Override public Response intercept(Chain chain) throws IOException {
        RealInterceptorChain realChain = (RealInterceptorChain) chain;
        HttpCodec httpCodec = realChain.httpStream();
        StreamAllocation streamAllocation = realChain.streamAllocation();
        RealConnection connection = (RealConnection) realChain.connection();
        Request request = realChain.request();
    
        long sentRequestMillis = System.currentTimeMillis();
        httpCodec.writeRequestHeaders(request);
    
        Response.Builder responseBuilder = null;
        if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
          if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
            httpCodec.flushRequest();
            responseBuilder = httpCodec.readResponseHeaders(true);
          }
    
          if (responseBuilder == null) {
            Sink requestBodyOut = httpCodec.createRequestBody(request, request.body().contentLength());
            BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
            // 注释1:往服务器写请求数据
            request.body().writeTo(bufferedRequestBody);
            bufferedRequestBody.close();
          } else if (!connection.isMultiplexed()) {
            streamAllocation.noNewStreams();
          }
        }
    
        httpCodec.finishRequest();
    
        if (responseBuilder == null) {
          responseBuilder = httpCodec.readResponseHeaders(false);
        }
    
        Response response = responseBuilder
            .request(request)
            .handshake(streamAllocation.connection().handshake())
            .sentRequestAtMillis(sentRequestMillis)
            .receivedResponseAtMillis(System.currentTimeMillis())
            .build();
    
    	// 注释2:去读到下发的数据,并构建Response
        int code = response.code();
        if (forWebSocket && code == 101) {
        response = response.newBuilder()
              .body(Util.EMPTY_RESPONSE)
              .build();
        } else {
          response = response.newBuilder()
              .body(httpCodec.openResponseBody(response))
              .build();
        }
        ...
        return response;
      }
    }
    
简洁易懂的 OkHttp 请求的流程源码分析 本文为 OkHttp 的第一篇文章,主要是对整个请求的流程的梳理,对 OkHttp 整体有一个感性的认识。 本文基于 OkHttp 最新的 4.8.1版本进行源分析的,源码是 Kotlin 写的,做好准备。 依赖 implementation 'com.squareup.okhttp3:okhttp:4.8.1' 整体流程 先写一个 Demo 作为源码分析的入口,首先分析异步请求的整体流程,然后再看同步请求的整体流程,从整体上把握 OkHttp 的请求流程 1.OkHttp 的基本使用 class O 阅读详情

相关推荐

okhttp3源码分析之请求流程

okhttp3版本3.14.9 请求流程 maven <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>3.14.9</version> </dependency&gt

Sid小杰的博客 2943

okhttp源码流程分析

版本说明 本文只考虑okhttp3.0.1版本HTTP1.1协议的源码实现(截止2019-3-20日,github上最新版本为3.14.0),虽然版本不同,但是对本文的主题HTTP1.1部分来说,流程变化不大。 Okhttp3.0.1关键类 (1). HttpEngine,http引擎,负责请求发送及接收流程。介绍几个关键的成员对象:client(OkHttpClient),client是...

111111的专栏 379

Android网络框架OkHttp源码分析(1)——请求流程

Android网络框架——OkHttp源码分析 前言 OkHttp是一个处理网络请求的高性能框架,由Square公司贡献。 它的出现替代了HttpUrlConnection和Apache HttpClient。 OkHttp采用了分层设计的思想,使用多层拦截器,每个拦截器解决一个问题,多层拦截器套在一起,就像设计模式中的装饰者模式一样,可以在保证每层功能高内聚的情况下,解决多样性的问题。 OkHttp源码的讲解可以分为两大部分: 请求流程 拦截器分析 接下来讲解第一部分: okhttp3源码分析之请求流

AthonyDavis的博客 578

Android之OkHttp源码分析二请求流程

1.OkHttp主流程分析图 2.OkHttp主流程源码分析 2.1.OkHttp完整的请求示例 public void asyncGet() throws IOException { //1.创建OkHttpClient客户端 OkHttpClient okHttpClient = new OkHttpClient(); //2.创建网络请求 Request reques...

Tiger的专栏 376

CTFshow MISC入门实战:010Editor+TweakPNG解决PNG隐写难题(附完整脚本)

本文详细介绍了在CTFshow MISC比赛中,如何利用010Editor和TweakPNG两款专业工具构建高效的PNG隐写分析工作流。文章从PNG文件结构解析入手,通过实战案例演示了如何协同使用010Editor进行二进制侦察与结构分析,以及使用TweakPNG进行数据块的精准编辑与删除,并最终提供了自动化分析脚本,帮助选手系统性地解决PNG隐写难题。

weixin_29252171的博客 74

AI工作流革命:从n8n到Sora2,揭秘自动化视频创作的底层逻辑

本文深入探讨了AI工作流在自动化视频创作中的应用,重点介绍了n8n、Coze和Sora2的组合如何实现从链接输入到视频输出的全流程自动化。通过三层架构解析、关键技术模块优化及成本控制策略,这套方案显著提升了视频生产效率,适用于电商、热点追踪等多种场景。

gg901的博客 1083

Android okhttp源码调用流程分析

okhttp 是一套专门为 JVM、Android 设计的 HTTP 客户端,支持同步阻塞调用和带有回调的异步调用,可以非常简单的在 Android 项目中实现网络请求。那么 okhttp 到底是如何做到异步请求?如何实现 HTTP 协议的?本文将通过简单案例对 okhttp 的主要源码进行解读。

孙先森的博客 612

【保研面试】线性代数面试复习

线性相关和无关 有向量组A,a1,a2…an , 如果存在不是全为0的k1,k2…kn,满足 a1 * k1 + a2 * k2… an * kn = 0 则向量组A称为线性相关(可以跟向量组A共面联系,即可以通过几个向量,表示出另外几个向量,故称为线性相关) 极大线性无关组 设有向量组A a1,a2…an(本身为线性相关) :若选出r个向量,满足以下条件 (1)向量组 r : 线性无关; (2) 向量组A中任意r+1个向量(若有的话)都线性相关, 则向量组r 是向量组A的一个极大线性无关组(简称为

云端筑梦师 6311

okhttp依赖_简洁易懂的 OkHttp 请求的流程源码分析

本文为 OkHttp 的第一篇文章,主要是对整个请求的流程的梳理,对 OkHttp 整体有一个感性的认识。 本文基于 OkHttp 最新的 4.8.1版本进行源分析的,源码是 Kotlin 写的,做好准备。依赖implementation 'com.squareup.okhttp3:okhttp:4.8.1'整体流程先写一个 Demo 作为源码分析的入口,首先分析异步请求的整体流程,然后再看同步请...

weixin_39584571的博客 288

数字IC设计避坑指南:为什么477条net的DRV问题无法修复?解析don‘t touch hierarchy的影响

本文深入解析了数字IC后端实现中,因“don't touch hierarchy”约束导致大量DRV违规(如477条net)无法自动修复的根本原因。文章以Cadence Innovus工具为例,详细阐述了DRV修复机制与设计保护约束的冲突原理,并提供了从日志定位、风险评估到分级解除约束的完整实战策略,帮助工程师有效解决此类设计收敛难题。

hope8的博客 290

S/4HANA Private Cloud 与 On-Premise 的 Key User Custom Fields 运输与升级避坑指南

本文探讨了SAP S/4HANA Cloud Private Edition和On-Premise系统中Key User Custom Fields的管理要点。文章指出,Custom Fields涉及元数据生成、对象一致性、传输治理等完整链路,操作不当会导致字段丢失或升级失败。关键建议包括:使用ATO Fiori App管理扩展项与传输绑定,配置正确的job user权限,避免在多系统并行开发同一字段。特别强调升级时需执行CFD_REGENERATE_IN_ONPREMISE报表,并通过标准传输机制推进变更

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 195

《OkHttp源码分析》之 OkHttp请求流程分析

本文作者091-2018Mirs_sir博客:http://my.youkuaiyun.com/a109340声明:本文由作者 Mirs_sir 授权发布,未经原作者允许请勿转载 看到上面蓝色字了吗,点下吧感谢 Mirs_sir 为我们带来OkHttp源码分析系列文章,目录如下:1.Http请求原理2.OkHttp的简单使用3.OkHttp的初始化4.OkHttp请求流程分析5.OkHttp的请求拦截链6.O

刘桂林 954

华为OD机试真题 新系统2026-04-01 Python&JS【计算数列位置N的值】

如果其前面的M个元素中,存在值相同的元素,则该位置上的数值等于前面M个数中最大的数值与最小的数值之如果其前面的M个元素中,不存在值相同的元素,则该位置上的数值等于前面M个数中最大的数值与最小的数值之差;1、输入M、N两个数,则按照以下规则形成一个数列;两个整数,用逗号分割,分别表示M和N。一个整数,表示数列第N个位置上的数值。2、数列的前M个元素的值为1到M;请计算该数列第N个位置上的数值。N取值范围:1<= N<=50。M取值范围:3<=M<=10。

MISAYAONE的博客 3221

OKHttp3--流程分析 核心类介绍 同步异步请求源码分析【二】

OKHTTP对于Android开发者的重要性可以说是不言而喻了,这里我采用的阅读源码方法是根据使用方法顺藤摸瓜查看源码和阅读几个重点类的相结合的方法去理解OKHTTP,我认为结合使用情况去阅读更能有代入感,更能加深理解,同时选择几个关键类辅助更能帮我们理解整体框架

Mango先生的博客 1856

Claude Code、Codex、Gemini CLI、OpenCode 和 OpenClaw 配置管理太麻烦?试试这个统一管理工具

还在为 Claude Code、Codex、Gemini CLI 等 AI CLI 配置烦恼?🤯 这款桌面工具支持五大助手统一管理,一键切换 50+ 服务商,MCP 和 Skills 集中管理 🛠️,跨平台支持,让你的 AI 编程更高效 ⚡

XiaoqiangClub的博客 913

200Gb/s以上速率的通道信号完整性设计和优化经验(二)

为满足200Gb/s信号完整性需求,需综合优化PCB、连接器、封装及SERDES架构。关键措施包括:采用低粗糙度铜箔与低损耗材料降低传输线损耗(200G目标0.55–0.6dB/cm);通过背钻工艺控制残桩长度至4±2mil;缩减连接器焊盘残桩至600μm以内以消除谐振;封装层面推进跳层走线、低Dk/Df材料与可控SMT工艺;采用PAM4调制与基于ADC/DSP的混合信号架构实现高效均衡。先进CMOS工艺(如纳米片器件)支撑复杂数字处理,协同设计是突破速率瓶颈的核心。

小孟同学的博客 147

OkHttp源码流程分析

前言 今天我们将来分析OkHttp的执行流程,从源码中来学习OkHttp的设计思想。 基本流程 使用OkHttp主要分为三步,想必同学们都比较熟悉了,如下: 创建OkHttpClient 创建Request 创建Call 那么我们主要来分析OkHttpClient和Call的源码执行了流程,至于Request,有兴趣的同学可以自行查看源码。 OkHttpClient 首先我们来看一下OkHtt...

weixin_33963189的博客 132

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

OkHttp 源码分析(一)—— 请求流程

这篇文章主要梳理一下 OkHttp 的请求流程,对 OkHttp 的实现原理有个整体的把握,再深入细节的实现会更加容易。 建议将 OkHttp 的源码下载下来,使用 IDEA 编辑器可以直接打开阅读。我这边也将最新版的源码下载下来,进行了注释,有需要的可以直接从 这里 下载查看。 基本使用 我们先看一下 OkHttp 的基本使用。 // 1、创建 Request Request request ...

weixin_33875564的博客 167

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Android Okhttp主流程源码分析

在OkHttp3中,其灵活性很大程度上体现在可以 intercept 其任意一个环节,而这个优势便是okhttp3整个请求响应架构体系的精髓所在,先放出一张主框架请求流程图,接着再分析源码。 String url = "http://wwww.baidu.com"; OkHttpClient okHttpClient = new OkHttpClient(); final Request requ...

假装你是大灰狼的专栏 727

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

aop方式向okhttp完成网络的监听拦截_简洁易懂的 OkHttp 请求的流程源码分析

本文为 OkHttp 的第一篇文章,主要是对整个请求的流程的梳理,对 OkHttp 整体有一个感性的认识。 本文基于 OkHttp 最新的 4.8.1版本进行源分析的,源码是 Kotlin 写的,做好准备。依赖implementation 'com.squareup.okhttp3:okhttp:4.8.1'整体流程先写一个 Demo 作为源码分析的入口,首先分析异步请求的整体流程,然后再看同步请...

weixin_36307713的博客 525

OkHttp源码学习笔记 (一) 主线流程源码分析

一、知识介绍: 1. 先说下OSI七层模型 应用层(指的是 http https rtmp) ↓ 表示层(如 数据加密解密/编码解码) ↓ 会话层(把 传输端口与接收端口建立会话) ↓ 传输层(这里就是他通过socket套接字抽象层 tcp长连接 udp非长连接) ↓ 网络层(通过IP查找目标主机 , 找到路径, 发送报包) ↓ 数据链路层(交换机) ↓ 物理层(物理传输 网线,把数据变成比特流 二进制数据传输) 2.在OSI之后转变衍生出TCP/IP四层模型 应用层(.

EksDimension的博客 312

okhttp源码简单流程分析

拦截器详细解析可以看大佬简书 "https://www.jianshu.com/p/6fac73f7570f"和 “https://www.jianshu.com/p/3c740829475c”okhttp请求流程构建一个okhttpClient对象,传入你想传入的对象,不传就是默认的;2:构建request对象3:okHttpClient.newCall 实际上返回的realCall类 继续调用RealCall.newRealCall。

alaleidd的博客 924

OKHttp调用流程及源码分析

从使用入手,追踪调用代码。使用如下: // 通过Builder模式创建OkHttpClient对象 OkHttpClient client = new OkHttpClient.Builder().build(); // 通过Builder模式创建Request对象 Request request = new Request.Builder().url("").build(); // 创建Call对象 Call call = client.newCall(request); try { // 同步请求

duncan891101的专栏 381

okhttp3x源码分析-请求流程

okhttp3的基本请求流程如上图所示,首先构建了网络请求所需的4个类(OkhttpClient,OkhttpClient.Builder,Request,Call),然后通过call.execute()或者call.enqueue(callback)来发起同步请求或者异步请求,下面我们来具体分析一下这两种方式如何进行网络请求的。

专注Java,Android领域开发 325

OKhttp源码流程分析笔记

okhttp主要包含构建者模式、责任链模式等。主要流程大致如下: 构建者模式构造request    okhttpclient对象   两套字段,在build方法返回赋值。 同步是调用在realCall类(实现Call接口)中的execute方法(设置拦截器链)中dispatcher的execute方法把请求添加到同步请求队列。在finally中调用dispatcher的finished方法,...

kerrysimon的博客 252
上一篇: Map相关源码分析
下一篇: Messenger夸进程通信的原理
1024Code
博客等级 码龄9年 122粉丝 9原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值