【笔记记录】使用Okhttp的WebSocket,并分析相关流程

相关使用方法简介
//导入Okhttp包
//okhttp
    implementation 'com.squareup.okhttp3:okhttp:3.10.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'

//创建okHttpClient
private val wsHttpClient :OkHttpClient by lazy {
        OkHttpClient.Builder()
            .readTimeout(10, TimeUnit.SECONDS)//设置读取超时时间
            .writeTimeout(10, TimeUnit.SECONDS)//设置写的超时时间
            .connectTimeout(10, TimeUnit.SECONDS)//设置连接超时时间
            .pingInterval(10, TimeUnit.SECONDS)
            .build()
    }
private lateinit var websocket:WebSocket

private lateinit var request:Request
//参数填充
request = Request.Builder()
            .url(webSocketServerurl)
            .build()


        websocket = wsHttpClient.newWebSocket(request,object : WebSocketListener() {
            override fun onOpen(webSocket: WebSocket, response: Response) {
                Log.i(TAG,"webSocket connection successful")
                super.onOpen(webSocket, response)
            }

            override fun onMessage(webSocket: WebSocket, text: String) {
                Log.i(TAG,"webSocket onMessage $text")
                super.onMessage(webSocket, text)
            }

            override fun onMessage(webSocket: WebSocket, bytes: ByteString) {
                Log.i(TAG,"webSocket onMessage ${bytes}")
                super.onMessage(webSocket, bytes)
            }

            override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
                Log.i(TAG,"webSocket onClosing")
                super.onClosing(webSocket, code, reason)
            }

            override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
                Log.i(TAG,"webSocket onClosed")
                super.onClosed(webSocket, code, reason)
            }

            override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
                Log.i(TAG,"webSocket onFailure")
                super.onFailure(webSocket, t, response)
            }
        })

//发送消息
websocket.send("发送的内容")
主相关流程分析
OkHttpWebsocket
//由RealWebSocket实现接口
public interface WebSocket {

  long queueSize();


  boolean send(String text);

  boolean send(ByteString bytes);

 
  boolean close(int code, @Nullable String reason);

  void cancel();

   //OkHttpClient进行继承
  interface Factory {
    WebSocket newWebSocket(Request request, WebSocketListener listener);
  }
}
OkHttpClient

每个okHttpClient都有自己的线程池和连接池,重用可减少在创建client上面的资源。(因此推荐使用单例,进行重复使用client)

//实现该接口,,Call用来发送http请求和读取响应数据
open class OkHttpClient : Call.Factory, WebSocket.Factory

//具体实现方法
@Override public WebSocket newWebSocket(Request request, WebSocketListener listener) {
    RealWebSocket webSocket = new RealWebSocket(request, listener, new Random(), pingInterval);
    webSocket.connect(this);
    return webSocket;
  }

RealWebSocket
//connent函数
public void connect(OkHttpClient client) {
    client = client.newBuilder()
        .eventListener(EventListener.NONE)
        .protocols(ONLY_HTTP1)
        .build();
    //在原本的请求上面增加配置
    final Request request = originalRequest.newBuilder()
        .header("Upgrade", "websocket")
        .header("Connection", "Upgrade")
        .header("Sec-WebSocket-Key", key)
        .header("Sec-WebSocket-Version", "13")
        .build();
    //Instance在OkHttpClient进行实例化,进行创建请求,RealCall
    call = Internal.instance.newWebSocketCall(client, request);
    call.enqueue(new Callback() {
      @Override public void onResponse(Call call, Response response) {
        try {
          checkResponse(response);
        } catch (ProtocolException e) {
          failWebSocket(e, response);
          closeQuietly(response);
          return;
        }

        // 将http流转化为WebSocket流,实例化StreamAllocation
        StreamAllocation streamAllocation = Internal.instance.streamAllocation(call);
         //设置当前的 connection 不能再创建新的流。
        streamAllocation.noNewStreams(); // Prevent connection pooling!
          //通过RealConnection创建流
        Streams streams = streamAllocation.connection().newWebSocketStreams(streamAllocation);

        // Process all web socket messages.
        try {
            //进行接口回调当前连接情况返回数据
          listener.onOpen(RealWebSocket.this, response);
          String name = "OkHttp WebSocket " + request.url().redact();
            //初始化读写,流的线程,   使用线程池周期性向发送ping帧,,线程池循环读取队列,进行发送该帧
          initReaderAndWriter(name, streams);
           //streamAllocation.connection()返回RealConnection
          streamAllocation.connection().socket().setSoTimeout(0);
           //启动WebSocketReader进行循环读取socket流
          loopReader();
        } catch (Exception e) {
          failWebSocket(e, null);
        }
      }

      @Override public void onFailure(Call call, IOException e) {
        failWebSocket(e, null);
      }
    });
  }
//当前类
//实现了websocket接口,用来提供发送消息,关闭等,取消等函数
//实现了WebSocketReader.FrameCallback接口
final class WebSocketReader {
  public interface FrameCallback {
    void onReadMessage(String text) throws IOException;
    void onReadMessage(ByteString bytes) throws IOException;
    void onReadPing(ByteString buffer);
    void onReadPong(ByteString buffer);
    void onReadClose(int code, String reason);
  }
}


//实现的接口,
@Override public void onReadMessage(String text) throws IOException {
    //回调监听器
    listener.onMessage(this, text);
  }

  @Override public void onReadMessage(ByteString bytes) throws IOException {
    listener.onMessage(this, bytes);
  }

  @Override public synchronized void onReadPing(ByteString payload) {
    pongQueue.add(payload);
    runWriter();
    receivedPingCount++;
  }

  @Override public synchronized void onReadPong(ByteString buffer) {
    // This API doesn't expose pings.
    receivedPongCount++;
    awaitingPong = false;
  }

  @Override public void onReadClose(int code, String reason) {
    if (code == -1) throw new IllegalArgumentException();

    Streams toClose = null;
    synchronized (this) {
      if (receivedCloseCode != -1) throw new IllegalStateException("already closed");
      receivedCloseCode = code;
      receivedCloseReason = reason;
      if (enqueuedClose && messageAndCloseQueue.isEmpty()) {
        toClose = this.streams;
        this.streams = null;
        if (cancelFuture != null) cancelFuture.cancel(false);
        this.executor.shutdown();
      }
    }

    try {
      listener.onClosing(this, code, reason);

      if (toClose != null) {
        listener.onClosed(this, code, reason);
      }
    } finally {
      closeQuietly(toClose);
    }
  }

  @Override public boolean send(String text) {
    if (text == null) throw new NullPointerException("text == null");
    return send(ByteString.encodeUtf8(text), OPCODE_TEXT);
  }

  @Override public boolean send(ByteString bytes) {
    if (bytes == null) throw new NullPointerException("bytes == null");
    return send(bytes, OPCODE_BINARY);
  }

//send具体方法
private synchronized boolean send(ByteString data, int formatOpcode) {
    // If this frame overflows the buffer, reject it and close the web socket.
    if (queueSize + data.size() > MAX_QUEUE_SIZE) {
      close(CLOSE_CLIENT_GOING_AWAY, null);
      return false;
    }

    // Enqueue the message frame.
    queueSize += data.size();
    //向队列添加一个数据帧,然后运行线程进行读写
    messageAndCloseQueue.add(new Message(formatOpcode, data));
    runWriter();
    return true;
  }

//runWriter
private void runWriter() {
    if (executor != null) {
        //线程池执行
      executor.execute(writerRunnable);
    }
  }

//writerRunnable
this.writerRunnable = new Runnable() {
      @Override public void run() {
        try {
          while (writeOneFrame()) {
          }
        } catch (IOException e) {
          failWebSocket(e, null);
        }
      }
    };

//writeOneFrame
主要内容,通过WebSocketWriter来对stream进行写入内容


//initReaderAndWriter
public void initReaderAndWriter(String name, Streams streams) throws IOException {
    synchronized (this) {
      this.streams = streams;
       //初始化 WebSocketWriter
      this.writer = new WebSocketWriter(streams.client, streams.sink, random);
      this.executor = new ScheduledThreadPoolExecutor(1, Util.threadFactory(name, false));
      if (pingIntervalMillis != 0) {
          //周期执行ping帧
        executor.scheduleAtFixedRate(
            new PingRunnable(), pingIntervalMillis, pingIntervalMillis, MILLISECONDS);
      }
      if (!messageAndCloseQueue.isEmpty()) {
          //连接时进行发送消息
        runWriter();
      }
    }
	//初始化WebSocketReader,传入了回调接口,用来时刻监听socket流内容
    reader = new WebSocketReader(streams.client, streams.source, this);
  }



//loopReader
public void loopReader() throws IOException {
    while (receivedCloseCode == -1) {
      //在WebScocketReader进行循环读取接受消息(判断为控住帧或消息帧,不同处理)
      reader.processNextFrame();
    }
  }

Internal

该抽象类,仅仅被OkHttpLcient实现,用来升级内部API

//被实现在OkHttpLcient内部
@Override public Call newWebSocketCall(OkHttpClient client, Request originalRequest) {
        return RealCall.newRealCall(client, originalRequest, true);
      }
RealCall
final class RealCall implements Call {


//第三个参数,当为websocket连接的时候,是true
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    // Safely publish the Call instance to the EventListener.
    RealCall call = new RealCall(client, originalRequest, forWebSocket);
    //设置调用连接过程中的监听事件,3.11 or 3.12 之后可能为最终版,目前是3.10.0版本
    call.eventListener = client.eventListenerFactory().create(call);
    return call;
  }
    
 //调用call.enqueue
//最终执行方法
@Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    //监听事件回调
    eventListener.callStart(this);
    //okhttpClient的dispatcher进行分发事件,,,
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }
    
    
    
//AsyncCall,,nameRunnable只是对线程改名
 final class AsyncCall extends NamedRunnable {
    private final Callback responseCallback;

    AsyncCall(Callback responseCallback) {
      super("OkHttp %s", redactedUrl());
      this.responseCallback = responseCallback;
    }

    String host() {
      return originalRequest.url().host();
    }

    Request request() {
      return originalRequest;
    }

    RealCall get() {
      return RealCall.this;
    }

    //线程池待执行内容
    @Override protected void execute() {
      boolean signalledCallback = false;
      try {
          //进行添加拦截器
        Response response = getResponseWithInterceptorChain();
        if (retryAndFollowUpInterceptor.isCanceled()) {
          signalledCallback = true;
            //回调失败
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          signalledCallback = true;
            //回调成功
          responseCallback.onResponse(RealCall.this, response);
        }
      } catch (IOException e) {
        if (signalledCallback) {
          // Do not signal the callback twice!
          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
        } else {
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }
  }
    
    //getResponseWithInterceptorChain,,,添加拦截器
Response getResponseWithInterceptorChain() throws IOException {
    // 构建一个栈顺序的拦截器
    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);
  }

    
    
 //最终,返回的reponse,包含拦截器
  public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
      RealConnection connection) throws IOException {
    if (index >= interceptors.size()) throw new AssertionError();

    calls++;

      //通过索引加一将拦截器串联
    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
        connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
        writeTimeout);
      //获取当前索引的拦截器
    Interceptor interceptor = interceptors.get(index);
      //再次传入所有拦截器进行继续串联
    Response response = interceptor.intercept(next);


    return response;
  }
Dispatcher
//异步请求执行策略
//ExecutorService在内部运行调用,若自定义线程池,需要满足最大调用数量
synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
       //进入等待队列执行
      readyAsyncCalls.add(call);
    }
  }
其他相关关键词作用和分析
RealConnection

用来实际监控流

在StreamAllocation的findConnection中被实例化并进行connect

//connect
 public void connect(int connectTimeout, int readTimeout, int writeTimeout,
      int pingIntervalMillis, boolean connectionRetryEnabled, Call call,
      EventListener eventListener) {
     ...
     while (true) {
      try {
          //如果是https请求并且使用了http代理服务器
        if (route.requiresTunnel()) {
            //开启隧道连接,隧道技术,进行屏蔽不同网络类型的差异,进行通信
          connectTunnel(connectTimeout, readTimeout, writeTimeout, call, eventListener);
          if (rawSocket == null) {
            // We were unable to connect the tunnel but properly closed down our resources.
            break;
          }
        } else {
            //使用socket连接
          connectSocket(connectTimeout, readTimeout, call, eventListener);
        }
        establishProtocol(connectionSpecSelector, pingIntervalMillis, call, eventListener);
        eventListener.connectEnd(call, route.socketAddress(), route.proxy(), protocol);
        break;
      } catch (IOException e) {
        closeQuietly(socket);
        closeQuietly(rawSocket);
        socket = null;
        rawSocket = null;
        source = null;
        sink = null;
        handshake = null;
        protocol = null;
        http2Connection = null;

        eventListener.connectFailed(call, route.socketAddress(), route.proxy(), null, e);

        if (routeException == null) {
          routeException = new RouteException(e);
        } else {
          routeException.addConnectException(e);
        }

        if (!connectionRetryEnabled || !connectionSpecSelector.connectionFailed(e)) {
          throw routeException;
        }
      }
    }

    if (route.requiresTunnel() && rawSocket == null) {
      ProtocolException exception = new ProtocolException("Too many tunnel connections attempted: "
          + MAX_TUNNEL_ATTEMPTS);
      throw new RouteException(exception);
    }

    if (http2Connection != null) {
      synchronized (connectionPool) {
        allocationLimit = http2Connection.maxConcurrentStreams();
      }
    }
     ...
 }


//connectTunnel
private void connectTunnel(int connectTimeout, int readTimeout, int writeTimeout, Call call,
      EventListener eventListener) throws IOException {
    //创建隧道请求对象,创建request
    Request tunnelRequest = createTunnelRequest();
    HttpUrl url = tunnelRequest.url();
    for (int i = 0; i < MAX_TUNNEL_ATTEMPTS; i++) {
        //创建socket连接
      connectSocket(connectTimeout, readTimeout, call, eventListener);
        //请求开启隧道
      tunnelRequest = createTunnel(readTimeout, writeTimeout, tunnelRequest, url);

      if (tunnelRequest == null) break; // Tunnel successfully created.

      // The proxy decided to close the connection after an auth challenge. We need to create a new
      // connection, but this time with the auth credentials.
      closeQuietly(rawSocket);
      rawSocket = null;
      sink = null;
      source = null;
      eventListener.connectEnd(call, route.socketAddress(), route.proxy(), null);
    }
  }

//createTunnel
private Request createTunnel(int readTimeout, int writeTimeout, Request tunnelRequest,
      HttpUrl url) throws IOException {
    // Make an SSL Tunnel on the first message pair of each SSL + proxy connection.
    String requestLine = "CONNECT " + Util.hostHeader(url, true) + " HTTP/1.1";
    while (true) {
      Http1Codec tunnelConnection = new Http1Codec(null, null, source, sink);
      source.timeout().timeout(readTimeout, MILLISECONDS);
      sink.timeout().timeout(writeTimeout, MILLISECONDS);
      tunnelConnection.writeRequest(tunnelRequest.headers(), requestLine);
      tunnelConnection.finishRequest();
      Response response = tunnelConnection.readResponseHeaders(false)
          .request(tunnelRequest)
          .build();
      // The response body from a CONNECT should be empty, but if it is not then we should consume
      // it before proceeding.
      long contentLength = HttpHeaders.contentLength(response);
      if (contentLength == -1L) {
        contentLength = 0L;
      }
      Source body = tunnelConnection.newFixedLengthSource(contentLength);
      Util.skipAll(body, Integer.MAX_VALUE, TimeUnit.MILLISECONDS);
      body.close();

      switch (response.code()) {
        case HTTP_OK:
          if (!source.buffer().exhausted() || !sink.buffer().exhausted()) {
            throw new IOException("TLS tunnel buffered too many bytes!");
          }
          return null;

        case HTTP_PROXY_AUTH:
          tunnelRequest = route.address().proxyAuthenticator().authenticate(route, response);
          if (tunnelRequest == null) throw new IOException("Failed to authenticate with proxy");

          if ("close".equalsIgnoreCase(response.header("Connection"))) {
            return tunnelRequest;
          }
          break;

        default:
          throw new IOException(
              "Unexpected response code for CONNECT: " + response.code());
      }
    }
  }


//connectSocket
 private void connectSocket(int connectTimeout, int readTimeout, Call call,
      EventListener eventListener) throws IOException {
    Proxy proxy = route.proxy();
    Address address = route.address();

    rawSocket = proxy.type() == Proxy.Type.DIRECT || proxy.type() == Proxy.Type.HTTP
        ? address.socketFactory().createSocket()
        : new Socket(proxy);

    eventListener.connectStart(call, route.socketAddress(), proxy);
    rawSocket.setSoTimeout(readTimeout);
    try {
      //打开socket链接
      Platform.get().connectSocket(rawSocket, route.socketAddress(), connectTimeout);
    } catch (ConnectException e) {
      ConnectException ce = new ConnectException("Failed to connect to " + route.socketAddress());
      ce.initCause(e);
      throw ce;
    }
    try {
      //对socket的输入和输出处理
      source = Okio.buffer(Okio.source(rawSocket));
      sink = Okio.buffer(Okio.sink(rawSocket));
    } catch (NullPointerException npe) {
      if (NPE_THROW_WITH_NULL.equals(npe.getMessage())) {
        throw new IOException(npe);
      }
    }
  }
WebsocketReader
//Websocket进行读写流的内容,并通过RealWebSocket传入的FrameCallback接口进行回调信息
//将信息回调到RealWebSocket,然后通过listener将信息回调到用户层面

//RealWebSocket进行调用方法,循环读取
void processNextFrame() throws IOException {
    readHeader();
    if (isControlFrame) {
       //读取控制帧
      readControlFrame();
    } else {
        //读取数据帧
      readMessageFrame();
    }
  }

//readMessageFrame
private void readMessageFrame() throws IOException {
    int opcode = this.opcode;
    if (opcode != OPCODE_TEXT && opcode != OPCODE_BINARY) {
      throw new ProtocolException("Unknown opcode: " + toHexString(opcode));
    }

    //读取内容具体实现
    readMessage();

    if (opcode == OPCODE_TEXT) {
        //进行回调返回信息
      frameCallback.onReadMessage(messageFrameBuffer.readUtf8());
    } else {
      frameCallback.onReadMessage(messageFrameBuffer.readByteString());
    }
  }
RetryAndFollowUpInterceptor

重定向拦截器,位于RealCall中实例化

//重定向最大次数
private static final int MAX_FOLLOW_UPS = 20;

@Override public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    Call call = realChain.call();
    EventListener eventListener = realChain.eventListener();

    //实例化
    StreamAllocation streamAllocation = new StreamAllocation(client.connectionPool(),
        createAddress(request.url()), call, eventListener, callStackTrace);
    this.streamAllocation = streamAllocation;

    int followUpCount = 0;
    Response priorResponse = null;
    while (true) {
      if (canceled) {
        streamAllocation.release();
        throw new IOException("Canceled");
      }

      Response response;
      boolean releaseConnection = true;
      try {
        //处理下层拦截器返回结果
        response = realChain.proceed(request, streamAllocation, null, null);
        releaseConnection = false;
      } catch (RouteException e) {
        // The attempt to connect via a route failed. The request will not have been sent.
          //获取下层拦截器返回的结果,然后判断是否可以重试。
        if (!recover(e.getLastConnectException(), streamAllocation, false, request)) {
          throw e.getLastConnectException();
        }
        releaseConnection = false;
        continue;
      } catch (IOException e) {
        // An attempt to communicate with a server failed. The request may have been sent.
        boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
        //获取下层拦截器返回的结果,然后判断是否可以重试。
        if (!recover(e, streamAllocation, requestSendStarted, request)) throw e;
        releaseConnection = false;
        continue;
      } finally {
        // We're throwing an unchecked exception. Release any resources.
        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)
                    .build())
            .build();
      }

     //判断是否需要重定向,内部解析响应码
      Request followUp = followUpRequest(response, streamAllocation.route());

      if (followUp == null) {
        if (!forWebSocket) {
          streamAllocation.release();
        }
        return response;
      }

      closeQuietly(response.body());

        //超过重定向次数
      if (++followUpCount > MAX_FOLLOW_UPS) {
        streamAllocation.release();
        throw new ProtocolException("Too many follow-up requests: " + followUpCount);
      }
		//不能重用的请求体
      if (followUp.body() instanceof UnrepeatableRequestBody) {
        streamAllocation.release();
        throw new HttpRetryException("Cannot retry streamed HTTP body", response.code());
      }

        //后续的请求是否可以重用Connection,则进行创建一个streamAllocation
      if (!sameConnection(response, followUp.url())) {
        streamAllocation.release();
        streamAllocation = new StreamAllocation(client.connectionPool(),
            createAddress(followUp.url()), call, eventListener, callStackTrace);
        this.streamAllocation = streamAllocation;
      } else if (streamAllocation.codec() != null) {
        throw new IllegalStateException("Closing the body of " + response
            + " didn't close its backing stream. Bad interceptor?");
      }

       //重定向的请求结果,赋值
      request = followUp;
      priorResponse = response;
    }
  }
StreamAllocation

使用该类的作用,屏蔽协议细节处理不同Connection的复用功能,,在RetryAndFollowUpInterceptor类中被实例化创建使用

StreamAllocation是用来协调ConnectionsStreamsCalls这三个实体的

HTTP通信 执行 网络请求(Call) 需要在 连接(Connection) 上建立一个新的 (Stream), StreamAllocation 是用来关联call和connection 的桥梁,它负责为一次call 寻找 connection而完成远程通信。

//newStream  ,获取一个 可用的连接(初始化resultConnection) 和 对应连接协议的编解码实例(resultCodec)
public HttpCodec newStream(
      OkHttpClient client, Interceptor.Chain chain, boolean doExtensiveHealthChecks) {
    int connectTimeout = chain.connectTimeoutMillis();
    int readTimeout = chain.readTimeoutMillis();
    int writeTimeout = chain.writeTimeoutMillis();
    int pingIntervalMillis = client.pingIntervalMillis();
    boolean connectionRetryEnabled = client.retryOnConnectionFailure();

    try {
      RealConnection resultConnection = findHealthyConnection(connectTimeout, readTimeout,
          writeTimeout, pingIntervalMillis, connectionRetryEnabled, doExtensiveHealthChecks);
      HttpCodec resultCodec = resultConnection.newCodec(client, chain, this);

      synchronized (connectionPool) {
        codec = resultCodec;
        return resultCodec;
      }
    } catch (IOException e) {
      throw new RouteException(e);
    }
  }

首先尝试使用当前的变量connection. 如果当前的connection为 null, 则通过Internal.instance.get(connectionPool, address, this, null); 在 连接池 中获取对应 address 的连接 赋值给 connection,如果当前的 connection不为null,则直接返回.
如果上一步没有找到可用连接,则看是否有其他可用路由。
如果有其他路由则先去连接池查询看是否有对应连接
没有的话则创建一个新的 RealConnection,并赋值给变量 connection.
在连接池中找到的话则直接返回。
然后新创建的连接开始握手连接,然后放入连接池,然后返回。

//findHealthyConnection最终调用findConnection
//返回一个承载新的stream的连接,优先级排序:已存在的连接,连接池,最后是建立一个新连接
 private RealConnection findConnection(int connectTimeout, int readTimeout, int writeTimeout,
      int pingIntervalMillis, boolean connectionRetryEnabled) throws IOException {
  ...
  //尝试使用当前的 connection,或者查找 连接池
  synchronized (connectionPool) {
    ...
    releasedConnection = this.connection;
    if (this.connection != null) {
      result = this.connection;
      releasedConnection = null;
    }
    if (!reportedAcquired) {
      releasedConnection = null;
    }
    if (result == null) {
      Internal.instance.get(connectionPool, address, this, null);
      if (connection != null) {
        foundPooledConnection = true;
        result = connection;
      } else {
        selectedRoute = route;
      }
    }
  }
  ...
  if (result != null) {
    return result;
  }

  //是否有其他的路由
  boolean newRouteSelection = false;
  if (selectedRoute == null && (routeSelection == null || !routeSelection.hasNext())) {
    newRouteSelection = true;
    routeSelection = routeSelector.next();
  }
  synchronized (connectionPool) {
    if (newRouteSelection) {
      //有其他路由则先去连接池查询看是否有对应连接
    }
    if (!foundPooledConnection) {
      ...
      //没有的话则创建一个新的RealConnection,并赋值给变量 connection
      result = new RealConnection(connectionPool, selectedRoute);
      acquire(result, false);
    }
  }
  // 在连接池中找到的话则直接返回
  if (foundPooledConnection) {
    eventListener.connectionAcquired(call, result);
    return result;
  }
  //新创建的连接开始握手连接
  result.connect(...);
  synchronized (connectionPool) {
    reportedAcquired = true;
    Internal.instance.put(connectionPool, result);
    ...
  }
  ...
  return result;
}
  • 11
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值