职责链办法

选用职责链办法,意思是用来处理相关事务职责的一条实施链,链上具有若干节点,,假定某个节点处理完了就能够根据实践事务需求传递给下一个节点持续处理或许回来处理完毕。举一个百科上的比方:

假天数假定是半天到1天,可能直接项目经理附和即可;

假定是1到3天的假期,需求项目主管附和;

假定是3天到30天,则需求部门经理阅览;

Okhttp的职责链形式

Okhttp职责链办法浅析

而在okhttp中,实例化类一共有五个阻遏器,其分别为

  1. 重试阻遏器 (RetryAndFollowUpInterceptor)
  2. 根底的源码编辑器手机版下载阻遏器(BridgeInterceptor)
  3. 缓存阻遏器 (CacheInterceptor)
  4. 联接的阻遏器(ConnectInterceptor)
  5. CallServerInterceptor

其作业的流程图websocket原理大体如下源码所示:

Okhttp的职责链形式

源码分析

重试阻遏器 (RetryAndFollowUpInterceptor)

  1. 首要看一下最源码本钱重要的intercept办法:其完成https协议了网络央求失利后,在一些必要的条件下,会从头进行网络央求 首要做了

    • 从chain中获取request,实例化StreamAllocation
    • 进入while循环,将实例化类央求传递给下一个阻遏器,等候response
    • 当遇到RouteException和IOEx缓存整理ception的时分会在抛出失常后重新再proceed(向阻遏器传递该request)
    • 当((RouteException || IOException)&&ecover==false)的时分才缓存视频兼并app下载会跳出死循环,抛弃持续传递
    • 下面的几个 if则是判别何时重传,并规划了重传的计数器
    @Override public Response intercept(Chain chain) throws IOEx源码共享网ception {
    Request request = chain.request();
    strwebsocket的缺陷和缺乏ea实例化英文mAllocatio源码年代n = new StreamAllocation(
    client.connectionPool(), createAddress(request.url()), callStackTrace);
    int followUpCount = 0;
    Responsewebsocket完成1对1谈天 priorResponse = null;
    while (true) {
    if (canceled)源码年代 {
    streamAllocation.release();
    throw new IOException("Cancel实例化目标是什么意思ed");
    }
    Respons实例化servlet类反常e response = null;
    boolean releaseConnection = true;
    try {
    response = ((RealIn实例化类terceptorChain) chain).proceed(request,WebSocket streamAllocation, null, null);缓存的视频怎样保存到本地
    releaseConnection = false;
    } catch (RouteException e) {
    // The attempt to connect via a routwebsocket的缺陷和缺乏e failed. The request will not have been sent.
    if (!recover(e.getLastConnectException(), falsehttps认证, request)) {
    throw e.get源码网站LastConnectException(缓存视频兼并);
    }
    releaseConnecti实例化类on = false;
    continue;
    } catch (IOException e) {
    // An attempt to communicate with a serv实例化目标是什么意思er failed. The req实例化类ueshttps域名t may have been sent.
    boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
    if (!reco源码网站ver(e, requestSendStarted, request)) throw e;
    releaseConnection = false;
    conti源码编辑器手机版下载nue;
    } finally {
    // We're thro源码编辑器手机版下载wing an unchttps安全问题hecked exception. Release any r缓存视频在手机哪里找esources.
    if (releaseConnection) {
    streamAllocation.streamFailed(null);
    streamAllocation.release();
    }
    }
    // Attach the prior response if it exists. Such responses never have a body.
    if (priorResponse != null) {
    response = response.newBuilder()
    .priorResponse(priorResponse.newBuilder()
    .body(null)
    .bu缓存视频兼并app下载ild())
    .build();
    }
    Request followUp = followUpRequ实例化est(responwebsocket的缺陷和缺乏se);
    if (followUp == null) {
    if (!forWebSocket) {
    streamAllocation.releawebsocket完成1对1谈天se();
    }
    return res实例化目标的关键字ponse;
    }
    closeQuietly(response源码共享网.body());
    if (++followUpCount > MAX_FOLLOW_UPS) {
    streamAllocation.release();
    throw new ProtocolException("Too many follow-up requests: " + followU源码本钱pCount);
    }
    if (followUp.body() instanceo实例化英文f UnrepeatableRequestB源码集市ody) {
    streamAllocation.release();
    throw new HttpRetryException("Cannot retr缓存视频怎样转入本地视频yWebSocket streamed HTTP body", r实例化esponse.code());
    }
    if (!sameConnection(response, followUp.url())) {
    streamAllocation.release();
    streamAllocation = new StreamAl源码之家location(
    client.connectionPool(), createwebsocket和socket差异Addr实例化目标是什么意思ess(followUp.url()), callStackTrace);
    } el源码之家se if (streamAllocation.codec(实例化一个类) != null) {
    throw new Illeghttps域名alStateException("Closing the body of " + response
    + " didn't close its backing stream. Bad interceptor?");
    }
    request = followUp;
    priorResponse = resp源码超市onse;
    }
    }
    
  2. okhttp经过followUpRequest办法完成了照应状况码的功用,包含重定向等,接下来详细看下其重定向功用的完成

    • 获取重定向地https域名址 loca源码之家tion
    • 从头创建和拼接央求新的Request
    • 从头将Request进行封装,之后发送网络央求并回来
    private Request followUpRequest(Response userResponse)源码集市 throws IOException {
    if (userRespon实例化目标的关键字se == null) throw new IllegalS缓存视频怎样转入本地视频tateException();
    Connection connection = streamAllocation.connection();
    Route route = connection != null缓存视频怎样转入本地视频
    ? connection.route()
    : null;
    int responseCode = userReswebsocket的缺陷和缺乏ponse.code();
    final String method = userResponse.request().method();
    switch (responseCode) {
    case HTTP_PROXY_AUTH:
    Proxy selectedProxy = route != null源码之家
    ? route.proxy()
    : client.proxy();
    if (sewebsocket是什么意思lectedProHTTPSxy.type() != Proxy.Type.HTTP) {
    throw new ProtocolExce实例化英文ption("Received HTTPwebsocket重连失利_PROXY_AUTH (407) codewebsocket的缺陷和缺乏 while not using proxy");
    }
    returwebsocket没准备好是什么意思n client.proxyAuthenticatwebsocket完成1对1谈天or().authenticate(route, userResponse);
    case HTTP_websocket面试题UNAUTHORIZED:
    return client.au源码网站thenticator().authenticate(route, userRehttps认证sponse);https域名
    case HTTP_PERM_REDIRECT:
    case HTTP_TEMP_REDIRECT:
    // "If the 307 or 308 status code is received in response to a request other than GET
    // or HEAD, the user agent MUST NOT automatically redir源码集市ect the request"
    if (!method.equals("GET") && !method.equals("HEAD")) {
    return null;
    }
    // fall-through实例化是什么意思
    cas缓存和下载的差异e HTTP_MULT_CHOICE:
    case HTTP_MOVED_PERM:
    case HTTP_MOVED_TEMP实例化目标:
    case HTTP_SEE_OTHER:
    //源码年代 Does the缓存视频兼并app下载 client allow redirects?
    if (!client.followRedirects()) rwebsocket面试题eturn null;
    String location = userResponse.header("Location");
    if (location == null) r缓存视频怎样转入本地视频eturn null;
    HttpUrl url = userRespons实例化e.r缓存视频怎样转入相册equest().url().resolve(location);
    // Don't follow redirects to unsupported protocols.
    if (url == null) return null;
    // If confiwebsocket的缺陷和缺乏gured, don't follow redirects between SSL and non-缓存SSL.
    b源码本钱oolean sameScheme = url.scheme().equals(userResponse.request().url().scheme());
    if (!sameScheme && !client.followSslRedirects()) return null;
    // Most redirects don't include a request body.
    Request.Builder requehttps安全问题stBui实例化lder = userResponse.request().newBuilder();WebSocket
    if (HttpMethod.permiwebsocket完成1对1谈天tsRequestBody(method)) {
    final boolean maintainBody = HttpMethod.redirectsWithBody(method);
    if (HttpMethod.red源码编辑器手机版下载irectsToGe缓存文件在哪里t(method)) {
    re源码之家questBuilder.method("源码GET", null);
    } els实例化需求e {
    Req源码共享网uestBody requestBody = maintainBody ? userResponse.request().body()源码超市 : null;
    requestBuil实例化一个类der.method(metwebsocket是什么意思hod, requestBo源码本钱dy);
    }
    if (!maintainBody实例化是什么意思) {
    requestBuilder.removeHwebsocket原理eader("Transfer-Enco缓存和下载的差异ding");
    requestBuilder.removeHeader("Content-Lengt源码网站h");
    r源码编辑器手机版下载equestBuilder.removeHeader("Content-Type");
    }
    }
    // When redirecting across hosts, drop all authentication headers. This
    // is potentially annoying to the application layer since they have no
    // way to retain them.
    if (!sameConnecwebsocket和socket差异tion(https协议user源码本钱Response, url)) {
    requestBuilder.removeHeader("Authorization");
    }
    return rwebsocket的缺陷和缺乏equestBuilder.url(url).bhttps认证uild();
    case HTTP_CLIENT_TIMEOUT:
    // 408's源码之家 are rare in practice, but somehttps协议 servers like HAProxy use this response code.源码之家 The
    // spec says that we may repeat the request witwebsocket完成1对1谈天houthttps和http的差异 mod缓存ifications. Modern browsers also
    // repeat the request (even non-idempot缓存视频兼并app下载ent ones.)
    if (userResponse.request().body() instanceof UnrepeatableRequestBody) {
    return null;
    }
    return userResponse.request();
    default:
    return null;
    }
    }
    

根底的阻遏器(Br实例化一个类idgeInterceptor)

正如名字相同,其对Network Request装备根柢的实例化目标网络信息,

  • websocket重连失利置Content-Type
  • /设置Host
  • 设置Connection头(User-Agenthttps协议、Cookie、Accept-Encoding)
  • 判别服务器是否支撑gzip紧缩格局,假定支撑则交给kio紧缩
public final class BridgeInterceptor implements Interceptor {
private final CookieJar cookieJar;
public BridgeInterceptor(CookieJar cookieJar) {
this.cookieJar = cookieJar;
}
@Override public Response intercept(Chain chain) throws IOEx缓存的视频怎样保存到本地ception {
Request userRequest = chain实例化数组.request();
Request.Builder requestBuilder = userRequest.newBuilder();
RequestBody body = userRequest.body();
if (body != null) {
MediaType co缓存视频在手机哪里找ntentType = bod源码超市y.content缓存视频在手机哪里找Type();
if (contentType != null) {
requestBuilder.header(websocket协议"Content-Type", contentType.toString());
}
long cowebsocket和socket差异ntentLength = body.contentLength();
if (contentLength != -1) {
requestBuilder.header("Contehttps安全问题nt-Length", Long.toString(cont缓存entLength));
rwebsocket的缺陷和缺乏equestBuilder.removeHeader("Tra源码n实例化需求sfer-Encoding");
} else {
requestBuilder.header("Transfer-EncodinHTTPSg", "chunked");
requestBuilder.removeHeade源码之家r("https安全问题Content-Length");
}
}
if (userRequest.header("Host") =源码编辑器= null) {
requestBuilder.header("Host", hostHeader(userRwebsocket没准备好是什么意思equest.url(), false));
}
if (userRequest.header("Connection") == null) {
requestB源码编辑器编程猫下载uilder.header("Connection", "Keep-Alive");
}
// If we add ahttps协议n "Accept-Encoding: gzip" header field we're responsible for alsohttps和http的差异 decompressing
// the transferwebsocket完成1对1谈天 stream.
boolean transparentGzip = false;
if (userRequest.header("Accept-Enc源码之家oding") == null && userRequest.header("Range") == nhttps域名ull) {
transparentGz源码编辑器编程猫下载ip源码共享网 = true;
requestBuilder.head实例化类er("Accept-Encoding", "gzip");
}
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",WebSocket Version.userAgent());
}
Response networkResponse = chain.proceed(requestBuilder.build());
HttpHHTTPSeaders.receiveHeaders(cookieJar, userReque源码st.u缓存视频在手机哪里找rl(), networkResponse.headers());
Response.Builder responseBuilder = networkResponse.newBuilder()
.request(userRequest);
if (transparentGzi源码本钱p
&& "gz缓存视频在手机哪里找ip".equalsIgnoreCase(networkResponse.header("Content-Encoding"))
&& HttpHeaders.hasBody(networkResponse)) {
GzipSource responseBody = new GzipSource(ne缓存视频怎样转入本地视频tworkResponse.body().sourhttps协议ce());
He缓存文件在哪里aders strippedHeaders = networkResponse.headers().newBuilder()
.removeAll("Content-Encoding")
.removeAll("C源码集市ontent-Length")
.build();
responseBuilder.headers(strippedHeaders);
responseBuilder.body(new RealResponseBody(strippedHeaders, Okio.b缓存文件在哪里uffer(responseBody)));
}
return responseBuilder.build();
}
/** Returns a 'Cookie' HTTP request headerwebsocket面试题 with all cookihttps和http的差异es, like {@c源码编辑器ode a=b; c=d}. */
private String cookieHeader(List<Cook实例化目标ie&源码gt; cookies) {
StringBuilder cookieHeader = new StringBuilder();
for (int i = 0, size = cookies.size(); i < size; i++) {
if (i > 0) {
cookieHeader.append("; ");
}
Cookie cookie = cookies.get(i);
cookieHeader.append(cookie.name()).append('=').app实例化end(cookie.value());
}
return cookieHeader.toString();
}
}

缓存阻遏器 (CacheInterceptor)

  • 关键在于Intercept办法中,其间的机制 上篇博客有说道实例化类,亦能够直实例化目标的关键字接查看代码的注释
public final class CacheInterceptor implements InterceptoWebSocketr {
final Inwebsocket和socket差异ter缓存文件在哪里nalCache cache;实例化servlet类反常
public CacheIn源码超市tercephttps安全问题tor(InternalChttps安全问题ache cac实例化he) {
this.cache = cache;
}
Response intercept(Chain chain) throws IOException {
//假定装备了缓存:优先从缓存中读取Respon实例化目标se
Resp缓存的视频怎样保存到本地onse cacheCandidate = cache != null
? cache.get(cha源码编辑器手机版下载in.websocket原理request())
: null;
long nowebsocket的缺陷和缺乏w = System.c实例化目标的关键字urrentTimeMillis();
//缓存战略,该战略经过某种规矩来判别缓存是否有用
CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get()源码编辑器手机版下载;
Request networkRequest = strategy.networkRequest;
Resp实例化一个类onse cacheRespon源码本钱se = strategy.cacheResponse;
。。。。
//假定根据缓存缓存视频在手机哪里找战略strategy制止运用网络,而且缓存无效,直接回来空的Response
iwebsocket和socket差异f (networkRequest ==https和http的差异 null && cacheResponwebsocket原理se == null) {
return new Response.Builder()
。。。
.code(源码本钱504)
.message("Unsatisfiable Request (only-if-cached)")
.b缓存视频怎样转入本地视频ody(Util.EMPTY_RESPONSE)//空的body
。。。
.build();
}
//假定根据缓存战略strategy制止运用网络,缓存视频变成本地视频且有缓存则直接运缓存视频怎样转入本地视频用缓存
if (networkRequest == null) {
return cacheResponse.newBuilder()
.cacheResponse(stripBody(cacheResponse))
.build实例化();
}
//需求网络
Response networkResponse = nul源码超市l;
try {websocket面试题//实施下一个阻遏器,主张网路央求
networkResponse = chain.缓存的视频怎样保存到本地proceed(networkRequest);
} finally {
。。。
}
//本地有缓存,
if (cacheResponse != null) {
//而且服务器回来304状况码(缓存视频变成本地视频阐明缓存还没过期或服务器资源没修正)
if (networkRespo缓存和下载的差异nse.code() == HTTP_NOT_MODIFIED) {
//运用缓存数据
Response response = cacheRespon实例化数组se.newBuilder()
。。。
.build();
。源码共享网。。。
//回来缓存
retur实例化是什么意思n response;
} else {
closeQuietly(cacheResponse.body());
}
}
//假定网络资源已经修正:运用网络照应回来源码本钱的最新数据
Response response = networkResponse.newBuilder()
.cachwebsocket是什么意思eResponse(stripBody(cacheRespowebsocket菜鸟教程nse))
.networkR缓存视频兼并esponse(stripBody(networkResponse))
.build();
//将最新的数据缓存起来
if (cache !=源码编辑器手机版下载 null) {
if (HttpHeaders.hasBody(response) && CacheStrategy.isCacheable(response, networkRequest)) {
CacheRequest cacheReq实例化目标的关键字uest = cache.put(response);
return cacheWritingResponse(cacheRequest, response);
}
。。。。
//回来最新的数据
retu实例化是什么意思rn response;
}
private static Respon源码超市se stripBody(Responsewebsocket完成1对1谈天 response) {
return response != null && response.缓存视频怎样转入相册body() != null
? response.newBuilder().bod缓存视频怎样转入本地视频y(null).build()
: response;
}
/**
* Returns a new sourhttps安全问题ce that writes byteHTTPSs to {@code cacheRequest} as they are r实例化目标ead by the source
* consumer. Th源码is is careful to discard bytes left over when the stream is closed; otherwise we
* may never exhaust the source stream and therefo源码编辑器手机版下载re not complete the cached respo源码年代nse.
*/
private Response cacheWritingResponse(final CacheRequest cacheRequest, Response response)
throws IOException {
// Some apps return a nul缓存l bod实例化类y; for compatibility we treat that like a nulwebsocket完成1对1谈天l ca实例化数组che request.
if (cacheRequest == null) return response;
Sink cacheBodyUnbuffered = cacheRequest.body();
if (cacheBodyUnbuffered == null) return response;
final BufferedSource source = response.body().source();
final BufferedSink cacheBody = Okio.buffer缓存和下载的差异(cawebsocket和socket差异cheBodyUnbuffered);
Source cacheW源码超市ritingSource = new Source() {
boole实例化类an cacheRequestClosed;
@Override public long read(Buffer sink, long byteC实例化目标是什么意思ount) throws IOException {
long bytesRead;
try {
bytesRead = source.read(sink, byteCount);
} catch (IOException e) {
if (!cacheRequestClosedHTTPS) {
cacheRequestClosed = true;
cacheRequest.abort(); // Failed to write a complete cache缓存视频兼并app下载 response.
}
throw e;
}
if (bytesRead == -1)websocket和socket差异 {
if (!cacheRequestClosed) {源码编辑器手机版下载
cacheRequestClosed = t源码编辑器手机版下载rue;
cacheBody.close(); // The cache源码编辑器编程猫下载 r实例化目标是什么意思esponse is complete!
}
return -1;
}
sink.copyTo(cacheBody.buffer(), sink.size() - bytesRead, bytesRead);
cacheBody.emitCompleteSegments();
return bytesRead;
}
@Override public Timeout timeout() {
return source.timeout();
}
@Override public void close() throws IOExcep源码编辑器编程猫下载tion {
if (!cacheRequestClosed
&& !discard(this, HttpCodec.DISCARD_STREAM实例化类_TIMEOUT_MILLIS, MILLISECONDS)) {
cacheRequestClosed = true;
cacheRequest.abort();
}
source.cl源码年代oseWebSocket(websocket没准备好是什么意思);
}
};
return response.newBuilder()源码编辑器编程猫下载
.body(new RealResponseBody(response.h实例化eaders(), Okio.buf实例化servlet类反常fer(源码本钱cacheW源码网站ritingSour缓存文件在哪里ce)))
.bui源码网站ld();
}
/** Combines cached headers with a network headers awebsocket的缺陷和缺乏s defined by RFC 2616, 13.5.3.websocket的缺陷和缺乏 */
private static Headers combine(Headers cachedHeaders, Head实例化目标的关键字ers networkHeaders) {
Headers.Builder result = new Headers.Builder();
for (int i = 0, size =https域名 cachedHeaders.size(); i < size; i++) {
String fieldName = cachedHeaders.name(i);
String value = cachedHeaders.value(i);
if ("Warning".equalsIgnoreCasewebsocket原理(fieldName) && value.startsWith(HTTPS"1")) {
cwebsocket是什么意思ontinue; // Drop 100-level freshness warnings.
}
if (!isEndToEnd(fieldName) || networkHeaders.get(fieldName) == null) {
Internal.instance.addLenient(result, fieldName, va源码之家lue);
}
}
for (int i = 0, size = networkHeaders.size(); i < size; i++) {
String fieldName = networkHeaders.name(i);
if ("Content-Length".equalsIgnoreCase(fieldName)) {
continue; // Ignore co源码集市ntent-length headers of validating responses.
}
if (isEndToEnd(fieldName)) {
Internal.instance.addLenient(result, fieldName, networkHeaderhttps协议s.value(i));
}
}实例化
return result.build();
}
/**
* Returns t缓存rue if {@code fieldNa实例化数组mwebsocket菜鸟教程e} is an end-to-end HTTP header, as defined by RFC 2616,
* 13.5.1.
*/
static boolean isEndToEnd(Stri缓存视频兼并ng fieldName) {
return !"Connection".equalsIgnoreCase(fieldName)
&& !"Keep-Alive".equalsIgnoreCase(fieldName)实例化需求
&& !"Proxy-Authentic实例化目标是什么意思ate".equalsIgnoreCase(fieldName)
&缓存视频在手机哪里找& !"Proxy-Authorization".equalsIgnoreCase(fieldName)
&amhttps安全问题p;& !"TE".equalsIgnor实例化需求eCase(fieldName)
&& !"Traiwebsocket的缺陷和缺乏lers".equalsIgnoreCase(fieldName)
&& !"Transfer-Encoding".equals源码集市Ignowebsocket重连失利reCase(fieldName)
&&缓存视频怎样转入相册amp; !"Upgrade"websocket原理.equalsIgnoreCase(fieldName);
}
}

联接的阻遏器(C源码超市onnectInterceptor)

打开了与服务器的链接,正式敞开了网络websocket是什么意思央求(打开了socket链接)

public final class ConnectInterceptorhttps认证 implements Intercept缓存视频变成本地视频or {
public final Okhttps认证HttpClient client;
public ConnectInterceptor(OkHttpClient client) {
thiswebsocket是什么意思.client = client;
}
@Override public Response intercept(Chain chain) throws IOEx源码ception {
RealInterceptorChain缓存 r源码网站ea缓存文件在哪里lChain = (RealInterceptorChain)缓存文件在哪里 chain;
Request request = r实例化一个类ealChain.request();
//实例化目标的关键字从阻遏器链里得到StreamAllocatiwebsocket协议on政策
StreamAllocation streamAllocation = realC源码之家hain.streamAllocation();
// We need the network to sat实例化类isfy this request.https安全问题 Possibly for validating a conditional GET.
boolean doExtensiveHealthChe缓存的视频怎样保存到本地cks = !request.mwebsocket原理ethod().https和http的差异equals("GET"websocket重连失利);
HttpCodec httpCodec = streamAllocation.newStreamwebsocket是什么意思(client, doExtensiveHealthChecks);
//获取realConnet缓存文件在哪里ion
RealConnection connection = streamAlloca缓存视频兼并app下载tion.connection();实例化是什么意思
//实施下一个阻遏器
return realChawebsocket重连失利in.proceed(r源码年代equest, streamAllocation, httpCodec, connection);
}
}

Ca源码之家llServerInterceptwebsocket原理or

作为okhttp的终究一个阻遏器,他的首要作用是向服务器发送央求,https域名 以及回来从服务器的到的response政策供客户端运用

相同的首要看一下最要害的Intercept办法,其间有如下几个要害点

  • 调用writeRequestHeader源码共享网s,作用为将http发送的网络央求构建成服务器能够承受源码之家的办法 如 “query”:”{rn user(login: “” 省掉。 其间writeRequestHeaders 又进一步骤用了writeRequest,完成了OKio的Sink
  • 检测是否有央求body部实例化需求分则是担任解析post,put等需求央求体的办法。假定服务器答应发送ReqeustBody,则调用sink类和ReqeustBody的writeTo办法发送央求体
  • 读取https协议服务器照应然后构建Response政策,首要构建缓存视频在手机哪里找央求builder政策, 其次经过ResopnseBu实例化servlet类反常ilder来创建Response政策
public Response intercept(Chain chain) throws IOExcep实例化类tion {
// 省掉部分代缓存文件在哪里码
// 获取HttpCodec
HttpCodec htt缓存视频兼并app下载pCodec = realChain.httpStream();
// 省掉部分代码
Request request = realChain.request();
//向服务器发送央求
httpCodec.writeRequestHeaders(request);
Response.Builder responseBuilder = null;
// 检测是否有央求body
if (HttpMethod.permitsRequewebsocket重连失利stBody(r实例化目标的关键字equest.缓存methhttps域名od()) && request.body() != null) {
if ("100-c源码编辑器ontinue".equalsIgnoreCase(request.header("Expect"))) {
httpCodec.flushRequest();
//构建responseBuilder政策
responseBuilder = httpCodec.readResponseHeaders(true);
}
//假定服务器答应发送央求body发送
if (responseBuilder == null) {
Sink requestBodyOut = httpCodec.createRequestBody(request, re源码年代quest.body().contentLength());
BufferedSink bufferedRequwebsocket是什么意思estBody = Okio.buffer(rwebsocket面试题equestBodyOut);
request.body().writeTo(websocket没准备好是什么意思bufferedRequestBody);
bufferedRequestBody.close();
} else if (!connection.isMultiplexed()) {
//省掉部分代码
}
}
//完毕央求
httpCodec.finishRequest();
//构建央求buidder政策
if (responseBuilder == null) {
responseBuilder = httpCodec.rewebsocket的缺陷和缺乏adResponseHeaders(false);
}
Response response =源码网站 responseBuilder
.request(request)
.handshake(streamAllocation.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
int code = response.code();
if (forwebsocket重连失利WebSocket && code == 101) {
//省掉部分代码
} else {
response = response.newBuilder()
.bo实例化英文dy(httpCodec.openResponseBody(response))
.build();
}
//省掉部分代码
r缓存视频怎样转入相册eturn response;
}
  • 能够看到,终究终究调用了openResponseBody(response),该办法定义在Http2Cohttps认证dec,盯梢进去,源码如下,首要做的作业为将Socket的输入流InputStream政策交给OkIo的Source政策,然后封装成RealResponseBody
@Ove源码之家rride public ResponseBody openResponseBody(Response response) throws IOException {
Source source = nHTTPSew StreamFinishingSource(stream.getSouwebsocket没准备好是什么意思rce());
return new RealResponshttps域名eBody(response.headers(), Okio.buffer(so源码之家urce));
}
  • 数据回来到客户端的时分,直接调用ResponseBody .

st源码ring办法即可,至websocket协议此我们便经过运用okhttp成功从网络获取到了相关的数据

public final String string() throws IOException {
BufferedSwebsocket重连失利ource source = sourcwebsocket的缺陷和缺乏e();
try {
Charset charset = Util.bowebsocket和socket差异mAwareCharset(source, ch源码集市arset());
return source.readString(charset);
} finally {
Util.closeQuietly(source);
}
}

阻遏器实例化目标在网络央求中的调用

阻遏器的调用流程大体能够如下图概括源码编辑器编程猫下载

[图片上传失利…(image-19cf46-16053缓存视频兼并37548472)]

  1. 在re实例化目标的关键字alcall类里面的execute函数实施调用getResponseWithInte缓存整理rceptorChain
  @Override protected void execute() {
boolean signalledCallback = false;
try {
Response response = ge缓存tResponseWithIntercepthttps安全问题orChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback = true;
responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} e实例化英文ls缓存视频怎样转入本地视频e {
signalle缓存和下载的差异dCallback = true;
responseCallback.onResponse(RealCall.this, response);
}
} catch (IOException e) {
if (signalledCallback) {
// Do not signal the callback twicewebsocket没准备好是什么意思!
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
} ewebsocket菜鸟教程lse {
responseCallback.onFailure(RealCall.this, e);
}
} finally {
client.dispatcher().finishe缓存视频怎样转入本地视频d(this)实例化;
}
}
}
  1. getResponseWithInterceptorChain能够清楚地看到五个阻遏器的添加
Response getResponseWithIntercepto缓存和下载的差异rChain() throws IOExcwebsocket完成1对1谈天eption {
// Build a full stack of interceptors.
List<Interceptor> intercepto实例化英文rs = new ArrayList<>实例化();
intercepto缓存视频怎样转入本地视频rs.addAll(client.interceptors());
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheIntercep实例化需求tor(client.internalCache()));
interceptors.add(nwebsocket协议ew Conn源码本钱ectIntercep实例化需求tor(client));
if (!forWe缓存视频兼并app下载bSocket) {
interceptors.addAll(c缓存视频怎样转入相册lient.netwo缓存整理rkInterceptors())缓存视频在手机哪里找;
}
interceptors.add(new CallServerInterce源码共享网ptor(forWebSocket));
Interceptor.Chain chain = new RealInterceptorChain(
interceptors, null, null, null, 0, originalRequest);
return chain缓存的视频怎样保存到本地.p源码本钱roceed(originalRequest);实例化一个类
}
  1. 在每一条链的Intercept方源码编辑器手机版下载法里面都调用了RealInterceptorChain.proc源码编辑器eed办法,确保了阻遏器链能够正常的运行。
response = ((RealInterceptorChain) chain).proceed(r缓存文件在哪里equest, streamAllo源码编辑器cation, null, null);
  1. 在终究的阻遏链里面回来了阻遏链,代表着五个阻遏器的实施完毕
return realChain.proceed(re源码年代quest, streamAllocation, httpCodec, connection);websocket重连失利

参看链接