okhttp-Transmitter

195 阅读1分钟
/**
 * Bridge between OkHttp's application and network layers. This class exposes high-level application
 * layer primitives: connections, requests, responses, and streams.
 *
 * <p>This class supports {@linkplain #cancel asynchronous canceling}. This is intended to have the
 * smallest blast radius possible. If an HTTP/2 stream is active, canceling will cancel that stream
 * but not the other streams sharing its connection. But if the TLS handshake is still in progress
 * then canceling may break the entire connection.
 */
public final class Transmitter {
  private final OkHttpClient client;
  private final RealConnectionPool connectionPool;
  private final Call call;
  private final EventListener eventListener;
  private final AsyncTimeout timeout = new AsyncTimeout() {
    @Override protected void timedOut() {
      cancel();
    }
  };
}

看注释,这个类是应用层和网络层之间的桥聊。这个类暴露了高水平的应用层的属性,connection等。

这个类支持请求的异步取消。

我们看下取消的逻辑

我们知道新建call是创建的realcall,取消也需要看下realcall的cancel

 @Override public void cancel() {
    transmitter.cancel();
  }

 transmitter的cancel
 public void cancel() {
    Exchange exchangeToCancel;
    RealConnection connectionToCancel;
    synchronized (connectionPool) {
      canceled = true;
      exchangeToCancel = exchange;
      connectionToCancel = exchangeFinder != null && exchangeFinder.connectingConnection() != null
          ? exchangeFinder.connectingConnection()
          : connection;
    }
    if (exchangeToCancel != null) {
取消数据交换
      exchangeToCancel.cancel();
    } else if (connectionToCancel != null) {
取消连接
      connectionToCancel.cancel();
    }
  }

接下来看超时机制

在realCall的execute方法中

  @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);
    }
  }

 public void timeoutEnter() {
    timeout.enter();
  }

我们看下timeout的enter方法

  fun enter() {
    check(!inQueue) { "Unbalanced enter/exit" }
    val timeoutNanos = timeoutNanos()
    val hasDeadline = hasDeadline()
    if (timeoutNanos == 0L && !hasDeadline) {
      return // No timeout and no deadline? Don't bother with the queue.
    }
    inQueue = true
此处开始计时
    scheduleTimeout(this, timeoutNanos, hasDeadline)
  }