httpclient connect連接請求方法源碼解讀
序
本文主要研究一下httpclient的connect
HttpClientConnectionOperator
org/apache/http/conn/HttpClientConnectionOperator.java
public interface HttpClientConnectionOperator {
void connect(
ManagedHttpClientConnection conn,
HttpHost host,
InetSocketAddress localAddress,
int connectTimeout,
SocketConfig socketConfig,
HttpContext context) throws IOException;
void upgrade(
ManagedHttpClientConnection conn,
HttpHost host,
HttpContext context) throws IOException;
}HttpClientConnectionOperator定義了connect及upgrade方法,它有一個默認的實現類為DefaultHttpClientConnectionOperator
DefaultHttpClientConnectionOperator
org/apache/http/impl/conn/DefaultHttpClientConnectionOperator.java
public class DefaultHttpClientConnectionOperator implements HttpClientConnectionOperator {
static final String SOCKET_FACTORY_REGISTRY = "http.socket-factory-registry";
private final Log log = LogFactory.getLog(getClass());
private final Lookup<ConnectionSocketFactory> socketFactoryRegistry;
private final SchemePortResolver schemePortResolver;
private final DnsResolver dnsResolver;
public DefaultHttpClientConnectionOperator(
final Lookup<ConnectionSocketFactory> socketFactoryRegistry,
final SchemePortResolver schemePortResolver,
final DnsResolver dnsResolver) {
super();
Args.notNull(socketFactoryRegistry, "Socket factory registry");
this.socketFactoryRegistry = socketFactoryRegistry;
this.schemePortResolver = schemePortResolver != null ? schemePortResolver :
DefaultSchemePortResolver.INSTANCE;
this.dnsResolver = dnsResolver != null ? dnsResolver :
SystemDefaultDnsResolver.INSTANCE;
}
//......
public void connect(
final ManagedHttpClientConnection conn,
final HttpHost host,
final InetSocketAddress localAddress,
final int connectTimeout,
final SocketConfig socketConfig,
final HttpContext context) throws IOException {
final Lookup<ConnectionSocketFactory> registry = getSocketFactoryRegistry(context);
final ConnectionSocketFactory sf = registry.lookup(host.getSchemeName());
if (sf == null) {
throw new UnsupportedSchemeException(host.getSchemeName() +
" protocol is not supported");
}
final InetAddress[] addresses = host.getAddress() != null ?
new InetAddress[] { host.getAddress() } : this.dnsResolver.resolve(host.getHostName());
final int port = this.schemePortResolver.resolve(host);
for (int i = 0; i < addresses.length; i++) {
final InetAddress address = addresses[i];
final boolean last = i == addresses.length - 1;
Socket sock = sf.createSocket(context);
sock.setSoTimeout(socketConfig.getSoTimeout());
sock.setReuseAddress(socketConfig.isSoReuseAddress());
sock.setTcpNoDelay(socketConfig.isTcpNoDelay());
sock.setKeepAlive(socketConfig.isSoKeepAlive());
if (socketConfig.getRcvBufSize() > 0) {
sock.setReceiveBufferSize(socketConfig.getRcvBufSize());
}
if (socketConfig.getSndBufSize() > 0) {
sock.setSendBufferSize(socketConfig.getSndBufSize());
}
final int linger = socketConfig.getSoLinger();
if (linger >= 0) {
sock.setSoLinger(true, linger);
}
conn.bind(sock);
final InetSocketAddress remoteAddress = new InetSocketAddress(address, port);
if (this.log.isDebugEnabled()) {
this.log.debug("Connecting to " + remoteAddress);
}
try {
sock = sf.connectSocket(
connectTimeout, sock, host, remoteAddress, localAddress, context);
conn.bind(sock);
if (this.log.isDebugEnabled()) {
this.log.debug("Connection established " + conn);
}
return;
} catch (final SocketTimeoutException ex) {
if (last) {
throw new ConnectTimeoutException(ex, host, addresses);
}
} catch (final ConnectException ex) {
if (last) {
final String msg = ex.getMessage();
throw "Connection timed out".equals(msg)
? new ConnectTimeoutException(ex, host, addresses)
: new HttpHostConnectException(ex, host, addresses);
}
} catch (final NoRouteToHostException ex) {
if (last) {
throw ex;
}
}
if (this.log.isDebugEnabled()) {
this.log.debug("Connect to " + remoteAddress + " timed out. " +
"Connection will be retried using another IP address");
}
}
}
}DefaultHttpClientConnectionOperator的connect先通過getSocketFactoryRegistry獲取Lookup<ConnectionSocketFactory>,再通過它獲取ConnectionSocketFactory,之后通過dnsResolver解析地址,再通過schemePortResolver解析port,然后通過ConnectionSocketFactory創(chuàng)建socket,并根據socketConfig設置socket的參數,最后執(zhí)行connectSocket,并綁定到conn
connectSocket
org/apache/http/conn/socket/PlainConnectionSocketFactory.java
public class PlainConnectionSocketFactory implements ConnectionSocketFactory {
public static final PlainConnectionSocketFactory INSTANCE = new PlainConnectionSocketFactory();
public static PlainConnectionSocketFactory getSocketFactory() {
return INSTANCE;
}
public PlainConnectionSocketFactory() {
super();
}
@Override
public Socket createSocket(final HttpContext context) throws IOException {
return new Socket();
}
@Override
public Socket connectSocket(
final int connectTimeout,
final Socket socket,
final HttpHost host,
final InetSocketAddress remoteAddress,
final InetSocketAddress localAddress,
final HttpContext context) throws IOException {
final Socket sock = socket != null ? socket : createSocket(context);
if (localAddress != null) {
sock.bind(localAddress);
}
try {
sock.connect(remoteAddress, connectTimeout);
} catch (final IOException ex) {
try {
sock.close();
} catch (final IOException ignore) {
}
throw ex;
}
return sock;
}
}PlainConnectionSocketFactory的createSocket直接new一個socket,其connectSocket方法則執(zhí)行sock.connect
socketConfig
resolveSocketConfig
org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java
private SocketConfig resolveSocketConfig(final HttpHost host) {
SocketConfig socketConfig = this.configData.getSocketConfig(host);
if (socketConfig == null) {
socketConfig = this.configData.getDefaultSocketConfig();
}
if (socketConfig == null) {
socketConfig = SocketConfig.DEFAULT;
}
return socketConfig;
}PoolingHttpClientConnectionManager的resolveSocketConfig先是從configData根據指定host獲取socketConfig,若為null則再從configData獲取默認的socketConfig,若為null則返回默認的socketConfig
setSocketConfig
org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java
public void setDefaultSocketConfig(final SocketConfig defaultSocketConfig) {
this.configData.setDefaultSocketConfig(defaultSocketConfig);
}
public void setSocketConfig(final HttpHost host, final SocketConfig socketConfig) {
this.configData.setSocketConfig(host, socketConfig);
}PoolingHttpClientConnectionManager提供了setDefaultSocketConfig、setSocketConfig方法
SocketConfig.DEFAULT
org/apache/http/config/SocketConfig.java
public class SocketConfig implements Cloneable {
public static final SocketConfig DEFAULT = new Builder().build();
//......
public static class Builder {
private int soTimeout;
private boolean soReuseAddress;
private int soLinger;
private boolean soKeepAlive;
private boolean tcpNoDelay;
private int sndBufSize;
private int rcvBufSize;
private int backlogSize;
Builder() {
this.soLinger = -1;
this.tcpNoDelay = true;
}
//......
}
}默認的socketConfig,除了tcpNoDelay為true,其他的都為false,然后soLinger為-1
小結
HttpClientConnectionOperator定義了connect及upgrade方法,它有一個默認的實現類為DefaultHttpClientConnectionOperator;DefaultHttpClientConnectionOperator的connect先通過getSocketFactoryRegistry獲取Lookup<ConnectionSocketFactory>,再通過它獲取ConnectionSocketFactory,之后通過dnsResolver解析地址,再通過schemePortResolver解析port,然后通過ConnectionSocketFactory創(chuàng)建socket,并根據socketConfig設置socket的參數,最后執(zhí)行connectSocket,并綁定到conn;默認的socketConfig,除了tcpNoDelay為true,其他的都為false,然后soLinger為-1。
以上就是httpclient connect連接請求方法源碼解讀的詳細內容,更多關于httpclient connect連接請求的資料請關注腳本之家其它相關文章!
- httpclient getPoolEntryBlocking連接池方法源碼解讀
- httpclient staleConnectionCheckEnabled獲取連接流程解析
- 解讀httpclient的validateAfterInactivity連接池狀態(tài)檢測
- httpclient的disableConnectionState方法工作流程
- 探索HttpClient中的close方法及其對連接的影響
- HttpClient的RedirectStrategy重定向處理核心機制
- HttpClient HttpRoutePlanner接口確定請求目標路由
- httpclient ConnectionHolder連接池連接保持源碼解析
相關文章
Spring中過濾器(Filter)和攔截器(Interceptor)到底啥區(qū)別詳解
在Spring框架中過濾器(Filter)和攔截器(Interceptor)都是用于處理HTTP請求的重要組件,但它們的工作原理和執(zhí)行順序有所不同,這篇文章主要介紹了Spring中過濾器(Filter)和攔截器(Interceptor)到底啥區(qū)別的相關資料,需要的朋友可以參考下2026-04-04
springboot打包不同環(huán)境配置以及shell腳本部署的方法
這篇文章主要給大家介紹了關于springboot打包不同環(huán)境配置以及shell腳本部署的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者使用springboot具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2019-03-03

