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
是用来协调Connections
、Streams
和Calls
这三个实体的
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;
}