美文网首页
OkHttp 请求网络服务器流程源码分析

OkHttp 请求网络服务器流程源码分析

作者: 有没有口罩给我一个 | 来源:发表于2019-06-06 16:56 被阅读0次

    概述

    HTTP是现代应用常用的一种应用程序与服务器交换网络数据的方式,高效地使用HTTP能让资源加载更快,节省带宽。OkHttp是一个高效的HTTP客户端,它有以下默认特性:

    • 支持HTTP/2,允许所有同一个主机地址的请求共享同一个socket连接;
    • 连接池减少请求时握手延时;
    • 透明的GZIP压缩减少响应数据的大小;
    • 缓存响应内容,避免一些完全重复的请求;

    当网络出现问题的时候OkHttp会自动恢复一般的连接问题,如果你的服务有多个IP地址,当第一个IP请求失败时,OkHttp会交替尝试来接你配置的其他IP地址,OkHttp默认使用现代TLS技术(TLS 1.3,ALPN,certificate pinning)初始化新的连接,当握手失败时会回退到TLS 1.0,这样做能实现更广泛的连接。

    OSI和TCP参考模型图


    osi和tcp模型.png

    总体流程

    整体流程:OkHttpClient构建的Request转换为Call,然后在RealCall中进行异步(AsyncCall)或同步任务,最后通过一系列的拦截器(interceptor)发出网络请求然后递归返回的response,大概就是这么个流程,,下面是OKHttp总体请求的流程时序图,包括同步和异步请求:


    okhttp.png

    上面的时序图是包括同步和异步的请求,而同步和异步请求的区别在于异步会开启线程池去请求服务器,其后面的逻辑就是基本一致都是调用getResponseWithInterceptorChain方法通过责任链模式的方式分别去通过每个链的节点处理Request,经过前面的节点处理过的Request会交给最后一个节点CallServerInterceptor去做真正的请求服务器的处理,最终拿到Response然后经过每个节点的处理,最终返回给client。

    我们这里先看一个简单的同步的GET请求。

    public class GetExample {
    OkHttpClient client = new OkHttpClient.Builder()
            .dispatcher(
                    new Dispatcher()
            ).build();
    
    String run(String url) throws IOException {
        Request request = new Request.Builder()
                .url(url)
                .build();
    
        try (Response response = client.newCall(request).execute()) {
            return response.body().string();
        }
    }
    
    public static void main(String[] args) throws IOException {
        GetExample example = new GetExample();
        String response = example.run("https://raw.github.com/square/okhttp/master/README.md");
        System.out.println(response);
        }
    }
    

    Okhttp的请求无非就是构造OkHttpClient 和Request,然后直接发起请求,Response response = client.newCall(request).execute()这是一个同步的请求,会阻塞当前线程,并返回Response,那么看看client.newCall(request).execute()到底做了什么?

      //OkHttpClient 
     @Override
    public Call newCall(Request request) {
        return RealCall.newRealCall(this, request, false /* for web socket */);
    }
    
    
     //RealCall 
    static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
        // Safely publish the Call instance to the EventListener.
        RealCall call = new RealCall(client, originalRequest, forWebSocket);
        call.transmitter = new Transmitter(client, call);
        return call;
    }
    

    开始OkHttpClient .newCall方法创建Call,Call是一个接口,它的实现类是RealCall,接着RealCall调用execute方法,代码如下所示。

      //RealCall 
    @Override
    public Response execute() throws IOException {
        synchronized (this) {
            if (executed) throw new IllegalStateException("Already Executed");
            executed = true;
        }
        transmitter.timeoutEnter();
        transmitter.callStart();
        try {
            client.dispatcher().executed(this);
            return getResponseWithInterceptorChain();//拦截器链的开始点
        } finally {
            client.dispatcher().finished(this);
        }
    }
    

    在execute方法中,首先判断该Call是否已经被执行了,如果已经被执行将抛出异常,然后调用dispatcher的executed方法,将call放入Dispatcher的同步队列runningSyncCalls中,接着在finish块中将call移除runningSyncCalls,即请求结束,那整个网络请求的一系列操作到底在哪,接着看RealCall.getResponseWithInterceptorChain方法?

    Response getResponseWithInterceptorChain() throws IOException {
        // Build a full stack of interceptors.
        List<Interceptor> interceptors = new ArrayList<>();
        interceptors.addAll(client.interceptors());
        //重试和重定向的拦截器
        interceptors.add(new RetryAndFollowUpInterceptor(client));
        //处理请求头的拦截器,如gzip
        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, transmitter, null, 0,
                originalRequest, this, client.connectTimeoutMillis(),
                client.readTimeoutMillis(), client.writeTimeoutMillis());
        boolean calledNoMoreExchanges = false;
        try {
    
            //拦截器链的开始
            Response response = chain.proceed(originalRequest);
    
            if (transmitter.isCanceled()) {
                closeQuietly(response);
                throw new IOException("Canceled");
            }
            return response;
        } catch (IOException e) {
            calledNoMoreExchanges = true;
            throw transmitter.noMoreExchanges(e);
        } finally {
            if (!calledNoMoreExchanges) {
                transmitter.noMoreExchanges(null);
            }
        }
    }
    

    在getResponseWithInterceptorChain方法中,主要是构造拦截器链RealInterceptorChain,紧接着 调用chain.proceed(originalRequest)方法开始执行拦截器链,代码如下。

    @Override
    public Response proceed(Request request) throws IOException {
        return proceed(request, transmitter, exchange);
    }
    
    public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)
            throws IOException {  
        
           //省略很多代码..................
    
        // Call the next interceptor in the chain.
        //调用链中的下一个拦截器。
        RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
                index + 1, request, call, connectTimeout, readTimeout, writeTimeout);
        Interceptor interceptor = interceptors.get(index);
        Response response = interceptor.intercept(next);
    
        //省略很多代码..................
    
        //一条链节点结束
        return response;
    }
    

    可看到在proceed方法中,又重新构造新的拦截器链RealInterceptorChain实例next ,接着取出拦截器并调用了interceptor方法,并将next 传进去,我们选择第一个拦截器RetryAndFollowUpInterceptor看看intercept方法到底做了什么?

    RetryAndFollowUpInterceptor 负责失败重试以及重定向

     @Override
    public Response intercept(Chain chain) throws IOException {
    
        Request request = chain.request();
        RealInterceptorChain realChain = (RealInterceptorChain) chain;
        Transmitter transmitter = realChain.transmitter();
    
        int followUpCount = 0;
        //重复请求响应,如果是重定向,就会有这个priorResponse,HTTP redirect or authorization
        Response priorResponse = null;
        while (true) {
            //预创建一个stream来承载request。 如果已经存在了connection,则优先使用现有connection。
            transmitter.prepareToConnect(request);
    
            if (transmitter.isCanceled()) {
                throw new IOException("Canceled");
            }
    
            Response response;
    
            //为true说明建立连接是成功的,并且返回了response
            boolean success = false;
            try {
                //当执行后面的操作抛出异常,可能我们需要重试连接
                response = realChain.proceed(request, transmitter, null);
                success = true;
            } catch (RouteException e) {
                //如果是Router连接失败,那么请求将不会再发送,直接把异常跑到上层应用
                if (!recover(e.getLastConnectException(), transmitter, false, request)) {
                    throw e.getFirstConnectException();
                }
                //那么继续重新连接
                continue;
            } catch (IOException e) {
                // 与服务器尝试通信失败,请求不会再发送。
                boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
                //判断需不需要重试
                if (!recover(e, transmitter, requestSendStarted, request)) throw e;
                continue;
            } finally {
                // //抛出未检查的异常,释放资源.
                if (!success) {
                    transmitter.exchangeDoneDueToException();
                }
            }
    
            // 满足先前存在的priorResponse,也就是第一次请求服务器时,服务器返回的响应就仅仅是状态码没有任何的数据。这样的response从来就没有body
            if (priorResponse != null) {
                response = response.newBuilder()
                        .priorResponse(priorResponse.newBuilder()
                                .body(null)
                                .build())
                        .build();
            }
    
            Exchange exchange = Internal.instance.exchange(response);
            Route route = exchange != null ? exchange.connection().route() : null;
    
            /**
             * 计算出响应接收userResponse的HTTP请求。
             * 这将添加身份验证标头,遵循重定向或处理客户端请求超时。
             * 如果后续操作不必要或不适用,则返回null。
             *
             * 注释说那么多,其实就是根据Http状态码决定重定向
             */
            Request followUp = followUpRequest(response, route);
    
    
            //不需要重定向
            if (followUp == null) {
                if (exchange != null && exchange.isDuplex()) {
                    transmitter.timeoutEarlyExit();
                }
                return response;
            }
    
    
            RequestBody followUpBody = followUp.body();
            if (followUpBody != null && followUpBody.isOneShot()) {
                return response;
            }
    
            closeQuietly(response.body());
    
            if (transmitter.hasExchange()) {
                exchange.detachWithViolence();
            }
    
            if (++followUpCount > MAX_FOLLOW_UPS) {
                throw new ProtocolException("Too many follow-up requests: " + followUpCount);
            }
    
            request = followUp;
            priorResponse = response;
        }
    }
    

    1、第一步,根据 response = realChain.proceed(request, transmitter, null);中直接调用了下一个拦截器,然后捕获可能的异常来进行相应的重试操作或者请求失败。
    2、根据第一步请求得到response,调用Request followUp = followUpRequest(response, route);followUp是Request类型,判断followUp 是否有重定向的操作,即followUp 不为null,就是有重定向,如果为null,说明不需要重定向,直接返回response。
    3、根据第二步,followUp 如果不为null,说明需要进行重定向,并把response赋值给priorResponse和把followUp赋值给request,而priorResponse是指上一次循环的响应,在方法体最下面有赋值。主要是为了重定向。如果发现上一次request的响应有重定向,则给当前响应的priorResponse赋值,并且把response的body置为空,接着继续下一步的请求。

    BridgeInterceptor

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request userRequest = chain.request();
        Request.Builder requestBuilder = userRequest.newBuilder();
    
    
        //检查request。将用户的request转换为发送到server的请求
        RequestBody body = userRequest.body();
        if (body != null) {
            MediaType contentType = body.contentType();
            if (contentType != null) {
                //自动增添加请求头 Content-Type
                requestBuilder.header("Content-Type", contentType.toString());
            }
            //请求体内容的长度
            long contentLength = body.contentLength();
            //如果传输长度不为-1,则表示完整传输
            if (contentLength != -1) {
                //设置头信息 Content-Length
                requestBuilder.header("Content-Length", Long.toString(contentLength));
                requestBuilder.removeHeader("Transfer-Encoding");
            } else {
                //如果传输长度为-1,则表示分块传输,自动设置头信息
                requestBuilder.header("Transfer-Encoding", "chunked");
                requestBuilder.removeHeader("Content-Length");
            }
        }
    
        if (userRequest.header("Host") == null) {
            requestBuilder.header("Host", hostHeader(userRequest.url(), false));
        }
    
        //如果没有设置头信息 Connection,则自动设置为 Keep-Alive
        if (userRequest.header("Connection") == null) {
            requestBuilder.header("Connection", "Keep-Alive");
        }
    
    
        //如果我们添加“Accept-Encoding:gzip”头字段,我们还负责解压缩传输流。实际上默认Okhttp已经添加的,告诉服务器接收数据使用gzip
        boolean transparentGzip = false;
        if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) {
            //如果我们没有在请求头信息里增加Accept-Encoding,在这里会自动设置头信息 Accept-Encoding = gzip
            transparentGzip = true;
            requestBuilder.header("Accept-Encoding", "gzip");
        }
        //Cookie的处理
        List<Cookie> cookies = cookieJar.loadForRequest(userRequest.url());
        if (!cookies.isEmpty()) {
            requestBuilder.header("Cookie", cookieHeader(cookies));
        }
    
        if (userRequest.header("User-Agent") == null) {
            requestBuilder.header("User-Agent", userAgent);
        }
    
    
        //执行下一步操作,得到Response
        Response networkResponse = chain.proceed(requestBuilder.build());
    
        HttpHeaders.receiveHeaders(cookieJar, userRequest.url(), networkResponse.headers());
    
        Response.Builder responseBuilder = networkResponse.newBuilder()
                .request(userRequest);
    
    
        //如果response的头信息里Content-Encoding = gzip,并且我们没有手动在请求头信息里设置 Accept-Encoding = gzip,
        // 则会进行 gzip 解压数据流
        if (transparentGzip && "gzip".equalsIgnoreCase(networkResponse.header("Content-Encoding"))
                && HttpHeaders.hasBody(networkResponse)) {
            //使用了GzipSource
            GzipSource responseBody = new GzipSource(networkResponse.body().source());
    
            Headers strippedHeaders = networkResponse.headers().newBuilder()
                    .removeAll("Content-Encoding")
                    .removeAll("Content-Length")
                    .build();
            responseBuilder.headers(strippedHeaders);
            String contentType = networkResponse.header("Content-Type");
            responseBuilder.body(new RealResponseBody(contentType, -1L, Okio.buffer(responseBody)));
        }
    
        return responseBuilder.build();
    }
    

    在BridgeInterceptor中主要是对request和response的header做处理,比如对request body做gzip压缩,这里需要注意的是,如果我们在代码里没有手动设置 Accept-Encoding = gzip ,那么 OkHttp 会自动处理 gzip 的解压缩;反之,你需要手动对返回的数据流进行 gzip 解压缩。

    CacheInterceptor

    @Override
    public Response intercept(Chain chain) throws IOException {
    
        //获取上一次缓存的response,有可能为null
        Response cacheCandidate = cache != null ? cache.get(chain.request()) : null;
    
    
        //获取到当前时间
        long now = System.currentTimeMillis();
    
        //long nowMillis, Request request, Response cacheResponse
        CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get();
        //networkRequest 不为null,说明强制缓存规则不生效
        Request networkRequest = strategy.networkRequest;
        //该请求的上次的缓存的结果
        Response cacheResponse = strategy.cacheResponse;
    
        if (cache != null) {
            cache.trackResponse(strategy);
        }
    
        if (cacheCandidate != null && cacheResponse == null) {
            closeQuietly(cacheCandidate.body()); // The cache candidate wasn't applicable. Close it.
        }
    
        // If we're forbidden from using the network and the cache is insufficient, fail.
        //从缓存策略上来说强制缓存生效,应该直接取上次缓存结果,但由于未知原因缓存的结果没有了或者上次返回就没有,这里直接返回了失败的Response
        if (networkRequest == null && cacheResponse == null) {
            return new Response.Builder()
                    .request(chain.request())
                    .protocol(Protocol.HTTP_1_1)
                    .code(504)
                    .message("Unsatisfiable Request (only-if-cached)")
                    .body(Util.EMPTY_RESPONSE)
                    .sentRequestAtMillis(-1L)
                    .receivedResponseAtMillis(System.currentTimeMillis())
                    .build();
        }
    
        // If we don't need the network, we're done.
        //强制缓存生效,按道理来说我们直接返回上次的cacheResponse就可以了,
        // 当然这里对Response的cacheResponse的body做了置空处理。
        if (networkRequest == null) {
            return cacheResponse.newBuilder()
                    .cacheResponse(stripBody(cacheResponse))
                    .build();
        }
    
    
        //强制缓存不生效,说明此时应该使用对比缓存,需要从服务端取数据:
        Response networkResponse = null;
        try {
            //执行网络
            networkResponse = chain.proceed(networkRequest);
        } finally {
            // If we're crashing on I/O or otherwise, don't leak the cache body.
            if (networkResponse == null && cacheCandidate != null) {
                closeQuietly(cacheCandidate.body());
            }
        }
    
        // If we have a cache response too, then we're doing a conditional get.
        //按照对比缓存规则,取完之后应该判断是否返回304,如果是应该使用缓存结果:
        if (cacheResponse != null) {
            if (networkResponse.code() == HTTP_NOT_MODIFIED) {
                Response response = cacheResponse.newBuilder()
                        .headers(combine(cacheResponse.headers(), networkResponse.headers()))
                        .sentRequestAtMillis(networkResponse.sentRequestAtMillis())
                        .receivedResponseAtMillis(networkResponse.receivedResponseAtMillis())
                        .cacheResponse(stripBody(cacheResponse))
                        .networkResponse(stripBody(networkResponse))
                        .build();
                networkResponse.body().close();
    
                // Update the cache after combining headers but before stripping the
                // Content-Encoding header (as performed by initContentStream()).
                cache.trackConditionalCacheHit();
    
                //更新缓存
                cache.update(cacheResponse, response);
                return response;
            } else {
                closeQuietly(cacheResponse.body());
            }
        }
    
    
        //缓存完全失效了,这个时候应该利用刚才网络请求的结果
        Response response = networkResponse.newBuilder()
                .cacheResponse(stripBody(cacheResponse))
                .networkResponse(stripBody(networkResponse))
                .build();
    
        if (cache != null) {
            if (HttpHeaders.hasBody(response) && CacheStrategy.isCacheable(response, networkRequest)) {
                // Offer this request to the cache.
                //保存到缓存中
                CacheRequest cacheRequest = cache.put(response);
                return cacheWritingResponse(cacheRequest, response);
            }
    
    
            //过滤不能做缓存的请求method
            if (HttpMethod.invalidatesCache(networkRequest.method())) {
                try {
                    cache.remove(networkRequest);
                } catch (IOException ignored) {
                    // The cache cannot be written.
                }
            }
        }
    
        return response;
    }
    

    http缓存分为两种:

    • 一种强制缓存,一种对比缓存,强制缓存生效时直接使用以前的请求结果,无需发起网络请求。
    • 对比缓存生效时,无论怎样都会发起网络请求,如果请求结果未改变,即服务端会返回304,但不会返回数据,数据从缓存中取,如果改变了会返回数据,那么就要对比缓存了。

    在CacheInterceptor中,networkRequest如果不为null,则说明强制缓存生效,也就意味着这次请求直接使用上次的结果,无需发起网络请求。而cacheResponse则是上次的缓存结果。整个缓存处理其实就是这两种情况的组合,当然这里就不展开讲,因为我们是将的请求过程。

    ConnectInterceptor

    @Override 
    public Response intercept(Chain chain) throws IOException {
        RealInterceptorChain realChain = (RealInterceptorChain) chain;
        Request request = realChain.request();
        Transmitter transmitter = realChain.transmitter();
    
        // We need the network to satisfy this request. Possibly for validating a conditional GET.
        boolean doExtensiveHealthChecks = !request.method().equals("GET");
        Exchange exchange = transmitter.newExchange(chain, doExtensiveHealthChecks);
    
        return realChain.proceed(request, transmitter, exchange);
    }
    

    代码很少,其实它所有的连接逻辑都放到了transmitter.newExchange方法中,这里细节有点复杂,反正就是建立socket连接各种机制,这会在下一篇文章中讲,这里不展开讲。

    CallServerInterceptor

    @Override
    public Response intercept(Chain chain) throws IOException {
        RealInterceptorChain realChain = (RealInterceptorChain) chain;
    
        //封装请求头,即conent-length,method,编码等等
        Exchange exchange = realChain.exchange();
        Request request = realChain.request();
    
        //当前时间
        long sentRequestMillis = System.currentTimeMillis();
    
        exchange.writeRequestHeaders(request);
    
    
        /**
         * http 100-continue用于客户端在发送POST数据给服务器前,征询服务器情况,
         * 看服务器是否处理POST的数据,如果不处理,客户端则不上传POST数据,如果处理,
         * 则POST上传数据。在现实应用中,通过在POST大数据时,才会使用100-continue协议。
         *
         * 如果客户端有POST数据要上传,可以考虑使用100-continue协议。加入头{"Expect":"100-continue"}
         * 如果没有POST数据,不能使用100-continue协议,因为这会让服务端造成误解。
         * 并不是所有的Server都会正确实现100-continue协议,如果Client发送Expect:100-continue消息后,在timeout时间内无响应,Client需要立马上传POST数据。
         * 有些Server会错误实现100-continue协议,在不需要此协议时返回100,此时客户端应该忽略。
         *
         *
         */
        boolean responseHeadersStarted = false;
        //当前request需要请求体,即post请求等方式,如果有,则进行封装
        Response.Builder responseBuilder = null;
        if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
            // 判断服务器是否允许发送body
            if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
                //sink写入请求
                exchange.flushRequest();
                responseHeadersStarted = true;
                //这里只是发送的header
                exchange.responseHeadersStart();
                //读取response
                responseBuilder = exchange.readResponseHeaders(true);
            }
    
            if (responseBuilder == null) {
                //向服务器发送requestbody,还判断了是否多路复用,不是全双工通讯,智能请求第一次就释放资源
                if (request.body().isDuplex()) {
                    // Prepare a duplex body so that the application can send a request body later.
                    exchange.flushRequest();
                    BufferedSink bufferedRequestBody = Okio.buffer(
                            exchange.createRequestBody(request, true));
                    request.body().writeTo(bufferedRequestBody);
                } else {
                    // Write the request body if the "Expect: 100-continue" expectation was met.
                    BufferedSink bufferedRequestBody = Okio.buffer(
                            exchange.createRequestBody(request, false));
                    request.body().writeTo(bufferedRequestBody);
                    //不是全双工通讯,智能请求第一次就释放资源
                    bufferedRequestBody.close();
                }
            } else {//不发送RequestBody
                exchange.noRequestBody();
                if (!exchange.connection().isMultiplexed()) {
                    // If the "Expect: 100-continue" expectation wasn't met, prevent the HTTP/1 connection
                    // from being reused. Otherwise we're still obligated to transmit the request body to
                    // leave the connection in a consistent state.
                    exchange.noNewExchangesOnConnection();
                }
            }
        } else {//不发送RequestBody
            exchange.noRequestBody();
        }
    
        if (request.body() == null || !request.body().isDuplex()) {
            //就是请求
            exchange.finishRequest();
        }
    
        if (!responseHeadersStarted) {
            exchange.responseHeadersStart();
        }
    
        if (responseBuilder == null) {
            responseBuilder = exchange.readResponseHeaders(false);
        }
    
        //返回response
        Response response = responseBuilder
                .request(request)
                .handshake(exchange.connection().handshake())
                .sentRequestAtMillis(sentRequestMillis)
                .receivedResponseAtMillis(System.currentTimeMillis())
                .build();
    
        int code = response.code();
    
        //100的状态码的处理继续发送请求,继续接受数据
        if (code == 100) {
            // server sent a 100-continue even though we did not request one.
            // try again to read the actual response
            response = exchange.readResponseHeaders(false)
                    .request(request)
                    .handshake(exchange.connection().handshake())
                    .sentRequestAtMillis(sentRequestMillis)
                    .receivedResponseAtMillis(System.currentTimeMillis())
                    .build();
    
            code = response.code();
        }
    
        exchange.responseHeadersEnd(response);
    
        if (forWebSocket && code == 101) {
            // Connection is upgrading, but we need to ensure interceptors see a non-null response body.
            response = response.newBuilder()
                    .body(Util.EMPTY_RESPONSE)
                    .build();
        } else {
            response = response.newBuilder()
                    .body(exchange.openResponseBody(response))
                    .build();
        }
    
        if ("close".equalsIgnoreCase(response.request().header("Connection"))
                || "close".equalsIgnoreCase(response.header("Connection"))) {
            exchange.noNewExchangesOnConnection();
        }
    
        //返回为空的处理
        if ((code == 204 || code == 205) && response.body().contentLength() > 0) {
            throw new ProtocolException(
                    "HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
        }
    
        return response;
    }
    
    • 判断是否允许上传requestBody, 写入http请求头信息;

    • 判断header中Expect域是否为100-continue,这个请求头字段的作用是在发送RequestBody前向服务器确认是否接受RequestBody,如果没有,则正常请求。如果有,则相当于一次简单的握手操作,则等待服务器返回的ResponseHeaders之后再继续,如果服务器接收RequestBody,会返回null;

    • 如果RequestBuilder为null,说明Expect不为100-continue或者服务器同意接收RequestBody。这时就开始向流中写入RequestBody;

    • 读取响应头信息 构建Response,写入原请求、握手情况、请求时间、得到结果的时间等;

    • 针对204/205状态码处理;

    最后就结束了,可能后面还会两篇文章介绍CacheInterceptor和ConnectionInterceptor这两个拦截器,看一下整个网络请求的时序图:


    okhttp.png

    这张图是画的同步请求的,其实同步和异步请求其实请求过程的处理是一样的,只不过异步请求前期会做一些并发的处理,其余在拦截器那部分都是一样的,感兴趣的话,可以去看看执行异步的源码,谢谢。

    相关文章

      网友评论

          本文标题:OkHttp 请求网络服务器流程源码分析

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