okhttp是square比较老的项目了,目前没多少人用了,可能大多数用square的retrofit替代了,不过retrofit的底层还是复用了okhttp的代码的。本文出于好奇分析下一次http请求从底到上的流程
基本流程
从最常见的demo开始吧,demo 从http://blog.youkuaiyun.com/lmj623565791/article/details/47911083 copy
//创建okHttpClient对象
OkHttpClient mOkHttpClient = new OkHttpClient();
//创建一个Request
final Request request = new Request.Builder()
.url("https://github.com/hongyangAndroid")
.build();
//new call
Call call = mOkHttpClient.newCall(request);
//请求加入调度
call.enqueue(new Callback()
{
@Override
public void onFailure(Request request, IOException e)
{
}
@Override
public void onResponse(final Response response) throws IOException
{
//String htmlStr = response.body().string();
}
});
从newCall开始
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
可见子类是RealCall
@Override public void enqueue(Callback responseCallback) {
...
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
enqueue代码,注意传入的参数是个新建立的AsyncCall
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
executorService就是java标准的线程池,那么还是返回头来看call是什么
final class AsyncCall extends NamedRunnable {
...
@Override protected void execute() {
...
Response response = getResponseWithInterceptorChain();
...
responseCallback.onResponse(RealCall.this, response);
...
}
}
getResponseWithInterceptorChain在同一个文件中,RealCall.java
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, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
可见这个是设计模式中的责任链模式,本文不关注其余的interceptor,只关注核心的ConnectInterceptor
@Override public Response intercept(Chain chain) throws IOException {
...
HttpCodec httpCodec = streamAllocation.newStream(client, chain, doExtensiveHealthChecks);
RealConnection connection = streamAllocation.connection();
return realChain.proceed(request, streamAllocation, httpCodec, connection);
}
在它的处理方法中,建立了真正的数据连接
public HttpCodec newStream(
OkHttpClient client, Interceptor.Chain chain, boolean doExtensiveHealthChecks) {
...
RealConnection resultConnection = findHealthyConnection(connectTimeout, readTimeout,
writeTimeout, connectionRetryEnabled, doExtensiveHealthChecks);
HttpCodec resultCodec = resultConnection.newCodec(client, chain, this);
...
}
其中的resultCodec表示了http的协议版本,是http1,http2或者是其他协议。
private RealConnection findHealthyConnection(int connectTimeout, int readTimeout,
int writeTimeout, boolean connectionRetryEnabled, boolean doExtensiveHealthChecks)
throws IOException {
while (true) {
RealConnection candidate = findConnection(connectTimeout, readTimeout, writeTimeout,
connectionRetryEnabled);
...
}
...
}
}
private RealConnection findConnection(int connectTimeout, int readTimeout, int writeTimeout,
boolean connectionRetryEnabled) throws IOException {
...
result = new RealConnection(connectionPool, selectedRoute);
...
// Do TCP + TLS handshakes. This is a blocking operation.
result.connect(
connectTimeout, readTimeout, writeTimeout, connectionRetryEnabled, call, eventListener);
routeDatabase().connected(result.route());
...
return result;
}
findConnection实际上代码很长的,逻辑复杂,所贴代码是很简化的。简单的说就是建立新的Connection并连接。
public void connect(int connectTimeout, int readTimeout, int writeTimeout,
boolean connectionRetryEnabled, Call call, EventListener eventListener) {
...
connectSocket(connectTimeout, readTimeout, call, eventListener);
...
}
依然是大幅度简化后的代码,建立socket连接
private void connectSocket(int connectTimeout, int readTimeout, Call call,
EventListener eventListener) throws IOException {
...
Platform.get().connectSocket(rawSocket, route.socketAddress(), connectTimeout);
...
}
使用平台相关代码做更近一步的工作,对于Android平台来说,代码在AndroidPlatform.java中
@Override public void connectSocket(Socket socket, InetSocketAddress address,
int connectTimeout) throws IOException {
...
socket.connect(address, connectTimeout);
...
}
这里的Socket就是java标准库中的java.net.Socket,后续调用到操作系统标准库,进而到内核等等和okhttp没啥关系了,okhttp的流程到此为止。
okhttp的功能
从上述的流程分析看,okhttp的流程没多复杂。但是它的作用不是体现在流程上的,它提供了多个完备的功能
从源码目录可以简单看出:
okhttp-master/okhttp/src/main/java/okhttp3/internal/cache
okhttp-master/okhttp/src/main/java/okhttp3/internal/cache2
okhttp-master/okhttp/src/main/java/okhttp3/internal/connection
okhttp-master/okhttp/src/main/java/okhttp3/internal/http
okhttp-master/okhttp/src/main/java/okhttp3/internal/http1
okhttp-master/okhttp/src/main/java/okhttp3/internal/http2
okhttp-master/okhttp/src/main/java/okhttp3/internal/io
okhttp-master/okhttp/src/main/java/okhttp3/internal/platform
okhttp-master/okhttp/src/main/java/okhttp3/internal/publicsuffix
okhttp-master/okhttp/src/main/java/okhttp3/internal/tls
okhttp-master/okhttp/src/main/java/okhttp3/internal/ws
1.缓存功能
2.输入输出Stream,物理Socket,逻辑连接,路由的管理
3.实现了http协议,包括http2和http1
4.优化的io功能,使用nio替代了io,优化了性能
5.多平台支持,对不同平台做不同差异化支持,默认的包括Android、jdk9和JdkWithJettyBootPlatform
6.安全层传输协议tls
7.websocket协议实现,rfc6455,是html5中的协议
除了主目录外还有
okhttp-master/okhttp-android-support Android的支持,主要是io方面的改动
okhttp-master/okhttp-apache apache接口兼容
okhttp-master/okhttp-logging-interceptor http日志相关
okhttp-master/okhttp-urlconnection java标准接口兼容
可以看出okhttp完全可以方便的替换HttpClient和HttpUrlConnection的使用。