连接拦截器中用到的复用连接池ConnectionPool传送门:https://www.jianshu.com/p/522b3c7bf333
先回忆一下整个拦截器的流程:
![](https://img.haomeiwen.com/i4999887/ba395ae4b58f67a7.png)
可以看到CallServerInterceptor是最后一个拦截器,主要工作就是,写入请求头、写入请求体,读取响应头、读取响应体。
/** This is the last interceptor in the chain. It makes a network call to the server.
* 将http请求写入到io流中,也可以从io流中读取服务器返回给我们客服端的数据
* */
public final class CallServerInterceptor implements Interceptor {
private final boolean forWebSocket;
public CallServerInterceptor(boolean forWebSocket) {
this.forWebSocket = forWebSocket;
}
@Override public Response intercept(@NonNull 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();
// 写入请求头
realChain.eventListener().requestHeadersStart(realChain.call());
httpCodec.writeRequestHeaders(request); // 向socket当中写入请求的头部的信息
realChain.eventListener().requestHeadersEnd(realChain.call(), request);
Response.Builder responseBuilder = null;
if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
// If there's a "Expect: 100-continue" header on the request, wait for a "HTTP/1.1 100
// Continue" response before transmitting the request body. If we don't get that, return
// what we did get (such as a 4xx response) without ever transmitting the request body.
// 如果请求中存在“Expect:100-continue”标头,请在发送请求主体之前等待“HTTP / 1.1 100 Continue”响应。
// 如果我们没有得到,请返回我们得到的内容(例如4xx响应),而不发送请求主体。
if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
httpCodec.flushRequest();
realChain.eventListener().responseHeadersStart(realChain.call());
responseBuilder = httpCodec.readResponseHeaders(true);
}
// 写入请求体
if (responseBuilder == null) {
// Write the request body if the "Expect: 100-continue" expectation was met.
realChain.eventListener().requestBodyStart(realChain.call());
long contentLength = request.body().contentLength();
CountingSink requestBodyOut =
new CountingSink(httpCodec.createRequestBody(request, contentLength));
BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
request.body().writeTo(bufferedRequestBody); // 向socket当中写入请求的body信息
bufferedRequestBody.close();
realChain.eventListener()
.requestBodyEnd(realChain.call(), requestBodyOut.successfulCount);
} else if (!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.
streamAllocation.noNewStreams();
}
}
httpCodec.finishRequest(); // 完成了整个网络请求的写入工作
if (responseBuilder == null) {
realChain.eventListener().responseHeadersStart(realChain.call());
responseBuilder = httpCodec.readResponseHeaders(false); // 读取网络响应的头部信息
}
Response response = responseBuilder
.request(request)
.handshake(streamAllocation.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
// 读取响应体
int code = response.code();
if (code == 100) {
// server sent a 100-continue even though we did not request one.
// try again to read the actual response
responseBuilder = httpCodec.readResponseHeaders(false);
response = responseBuilder
.request(request)
.handshake(streamAllocation.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
code = response.code();
}
realChain.eventListener()
.responseHeadersEnd(realChain.call(), response);
if (forWebSocket && code == 101) { // 读取网络请求的body信息
// 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(httpCodec.openResponseBody(response))
.build();
}
if ("close".equalsIgnoreCase(response.request().header("Connection"))
|| "close".equalsIgnoreCase(response.header("Connection"))) {
streamAllocation.noNewStreams();
}
if ((code == 204 || code == 205) && response.body().contentLength() > 0) {
throw new ProtocolException(
"HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
}
return response;
}
static final class CountingSink extends ForwardingSink {
long successfulCount;
CountingSink(Sink delegate) {
super(delegate);
}
@Override public void write(Buffer source, long byteCount) throws IOException {
super.write(source, byteCount);
successfulCount += byteCount;
}
}
}
到这里说所有的拦截器就分析完了,我们总结一下OkHttp中一次网络请求的大致过程:
1.Call对象对请求的封装
2.dispatch对请求的分发
3.getResponseWithInterceptorChain()的使用
具体:
RetryAndFollowUpInterceptor
CacheInterceptor
BridgeInterceptor
ConnectInterceptor
CallServerInterceptor
附上一张整体流程图:
![](https://img.haomeiwen.com/i4999887/74004581d8478eb7.png)
OkHttp入门用法的传送门:https://www.jianshu.com/p/500abf06f447
网友评论