httpclient connect連接請(qǐng)求方法源碼解讀
序
本文主要研究一下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方法,它有一個(gè)默認(rèn)的實(shí)現(xiàn)類為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先通過(guò)getSocketFactoryRegistry獲取Lookup<ConnectionSocketFactory>
,再通過(guò)它獲取ConnectionSocketFactory,之后通過(guò)dnsResolver解析地址,再通過(guò)schemePortResolver解析port,然后通過(guò)ConnectionSocketFactory創(chuàng)建socket,并根據(jù)socketConfig設(shè)置socket的參數(shù),最后執(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一個(gè)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根據(jù)指定host獲取socketConfig,若為null則再?gòu)腸onfigData獲取默認(rèn)的socketConfig,若為null則返回默認(rèn)的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; } //...... } }
默認(rèn)的socketConfig,除了tcpNoDelay為true,其他的都為false,然后soLinger為-1
小結(jié)
HttpClientConnectionOperator定義了connect及upgrade方法,它有一個(gè)默認(rèn)的實(shí)現(xiàn)類為DefaultHttpClientConnectionOperator;DefaultHttpClientConnectionOperator的connect先通過(guò)getSocketFactoryRegistry獲取Lookup<ConnectionSocketFactory>
,再通過(guò)它獲取ConnectionSocketFactory,之后通過(guò)dnsResolver解析地址,再通過(guò)schemePortResolver解析port,然后通過(guò)ConnectionSocketFactory創(chuàng)建socket,并根據(jù)socketConfig設(shè)置socket的參數(shù),最后執(zhí)行connectSocket,并綁定到conn;默認(rèn)的socketConfig,除了tcpNoDelay為true,其他的都為false,然后soLinger為-1。
以上就是httpclient connect連接請(qǐng)求方法源碼解讀的詳細(xì)內(nèi)容,更多關(guān)于httpclient connect連接請(qǐng)求的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- httpclient getPoolEntryBlocking連接池方法源碼解讀
- httpclient staleConnectionCheckEnabled獲取連接流程解析
- 解讀httpclient的validateAfterInactivity連接池狀態(tài)檢測(cè)
- httpclient的disableConnectionState方法工作流程
- 探索HttpClient中的close方法及其對(duì)連接的影響
- HttpClient的RedirectStrategy重定向處理核心機(jī)制
- HttpClient HttpRoutePlanner接口確定請(qǐng)求目標(biāo)路由
- httpclient ConnectionHolder連接池連接保持源碼解析
相關(guān)文章
java實(shí)現(xiàn)Excel轉(zhuǎn)換為圖片
在實(shí)際開發(fā)過(guò)程中,經(jīng)常會(huì)有這樣的需求,需要將Excel表格或特定區(qū)域轉(zhuǎn)換為圖片,所以小編今天就來(lái)為大家介紹一下如何使用Java將Excel轉(zhuǎn)化為圖片吧2023-10-10親測(cè)SpringBoot參數(shù)傳遞及@RequestBody注解---踩過(guò)的坑及解決
這篇文章主要介紹了親測(cè)SpringBoot參數(shù)傳遞及@RequestBody注解---踩過(guò)的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10struts2中實(shí)現(xiàn)多個(gè)文件同時(shí)上傳代碼
struts2中實(shí)現(xiàn)多個(gè)文件同時(shí)上傳代碼,需要的朋友可以參考一下2013-04-04Mybatis無(wú)法獲取帶有下劃線前綴的字段的值問(wèn)題
這篇文章主要介紹了Mybatis無(wú)法獲取帶有下劃線前綴的字段的值問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Mybatis執(zhí)行流程、緩存原理及相關(guān)面試題匯總
最近剛學(xué)完MyBatis,趁著大好機(jī)會(huì),總結(jié)一下它的執(zhí)行流程,面試也愛問(wèn)這個(gè),下面這篇文章主要給大家介紹了關(guān)于Mybatis執(zhí)行流程、緩存原理及相關(guān)面試題的相關(guān)資料,需要的朋友可以參考下2022-02-02Java簡(jiǎn)單使用EasyExcel操作讀寫excel的步驟與要點(diǎn)
相信現(xiàn)在很多搞后端的同學(xué)大部分做的都是后臺(tái)管理系統(tǒng),那么管理系統(tǒng)就肯定免不了Excel的導(dǎo)出導(dǎo)入功能,下面這篇文章主要給大家介紹了關(guān)于Java簡(jiǎn)單使用EasyExcel操作讀寫excel的步驟與要點(diǎn),需要的朋友可以參考下2022-09-09如何動(dòng)態(tài)替換Spring容器中的Bean
這篇文章主要介紹了如何動(dòng)態(tài)替換Spring容器中的Bean,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08