connect方法分析
来源:互联网 发布:mac air怎么截屏 编辑:程序博客网 时间:2024/06/04 19:18
2,connect方法
HttpURLConnectionImpl的connect方法如下,
public final void connect() throws IOException { initHttpEngine(); boolean success; do { success = execute(false); } while (!success);}
首先调用initHttpEngine方法构造HttpEngine对象,然后调用execute方法进行连接,
2.1 构造HttpEngine对象
HttpURLConnectionImpl的initHttpEngine方法如下,
httpEngine = newHttpEngine(method, null, null, null);
在newHttpEngine方法的最后会构造HttpEngine对象,
return new HttpEngine(engineClient, request, bufferRequestBody, true, false, connection, null, requestBody, priorResponse);
2.2 execute连接
调用流程图如下,
HttpURLConnectionImpl的execute方法主要逻辑如下,
try { httpEngine.sendRequest();
调用HttpEngine对象的sendRequest发送请求,在该方法中会进行连接,
if (connection == null) { connect();}
如果Connection对象connection为空,就调用connect方法进行连接, connect方法主要逻辑如下,
1,首先调用createAddress创建Address对象,
address = createAddress(client, networkRequest);
2,然后调用nextConnection方法创建Connection对象并进行连接,
connection = nextConnection();
nextConnection方法如下,
Connection connection = createNextConnection();Internal.instance.connectAndSetOwner(client, connection, this, networkRequest);
首先调用createNextConnection方法构造Connection对象,然后调用Internal的connectAndSetOwner方法进行连接。
Internal是一个abstract类,定义如下,
public abstract class Internal {
有一个static变量instance,
public static Internal instance;
现在问题是哪个类继承了Internal并且实现了对应的方法呢?
在源码下面全局搜索,居然没有类继承Internal! 后来才发现,是在OkHttpClient中内部匿名实现的。
并且OkHttpClient是在HttpHandler的createHttpOkUrlFactory方法中构造的,
OkHttpClient client = new OkHttpClient();
Internal在OkHttpClient是一个static的代码块,
Internal.instance = new Internal() { @Override public Transport newTransport( Connection connection, HttpEngine httpEngine) throws IOException { return connection.newTransport(httpEngine); }•••
其connectAndSetOwner方法如下,
@Override public void connectAndSetOwner(OkHttpClient client, Connection connection, HttpEngine owner, Request request) throws RouteException { connection.connectAndSetOwner(client, owner, request);}
Connection的connectAndSetOwner逻辑如下,
if (!isConnected()) { List<ConnectionSpec> connectionSpecs = route.address.getConnectionSpecs(); connect(client.getConnectTimeout(), client.getReadTimeout(), client.getWriteTimeout(), request, connectionSpecs, client.getRetryOnConnectionFailure()); if (isSpdy()) { client.getConnectionPool().share(this); } client.routeDatabase().connected(getRoute());}
如果还未连接,则调用connect方法进行连接。
2.3 socket连接
Connection的connect调用流程图如下,
Connection的connect的主要逻辑如下,
1,构造SocketConnector对象,
SocketConnector socketConnector = new SocketConnector(this, pool);
2,构造SocketConnector的内部类ConnectedSocket对象,
if (route.address.getSslSocketFactory() != null) { // https:// communication connectedSocket = socketConnector.connectTls(connectTimeout, readTimeout, writeTimeout, request, route, connectionSpecs, connectionRetryEnabled);} else { // http:// communication. if (!connectionSpecs.contains(ConnectionSpec.CLEARTEXT)) { throw new RouteException( new UnknownServiceException( "CLEARTEXT communication not supported: " + connectionSpecs)); } connectedSocket = socketConnector.connectCleartext(connectTimeout, readTimeout, route);}
如果是https网址请求,就调用SocketConnector的connectTls方法创建ConnectedSocket对象,
否则就调用connectCleartext方法创建ConnectedSocket对象。
3,最后为Connection的变量赋值,
socket = connectedSocket.socket;handshake = connectedSocket.handshake;protocol = connectedSocket.alpnProtocol == null ? Protocol.HTTP_1_1 : connectedSocket.alpnProtocol;
SocketConnector的connectCleartext方法如下,
public ConnectedSocket connectCleartext(int connectTimeout, int readTimeout, Route route) throws RouteException { Socket socket = connectRawSocket(readTimeout, connectTimeout, route); return new ConnectedSocket(route, socket); }
首先调用connectRawSocket方法获取Socket对象,然后利用Socket对象构造并返回ConnectedSocket对象。
connectRawSocket方法的逻辑如下,
Platform platform = Platform.get(); try { Proxy proxy = route.getProxy(); Address address = route.getAddress(); Socket socket; if (proxy.type() == Proxy.Type.DIRECT || proxy.type() == Proxy.Type.HTTP) { socket = address.getSocketFactory().createSocket(); } else { socket = new Socket(proxy); } socket.setSoTimeout(soTimeout); platform.connectSocket(socket, route.getSocketAddress(), connectTimeout); return socket; } catch (IOException e) { throw new RouteException(e); }
首先获取Socket对象,然后调用Platform的connectSocket方法。
Platform这个类还是有点内涵,先来分析一下。
Platform的get方法如下,
public static Platform get() { return PLATFORM;}
PLATFORM是Platform对象,并且是调用findPlatform方法获取
private static final Platform PLATFORM = findPlatform();
findPlatform方法根据android 系统进行构造Platform对象,
1,如果是android 2.3以上版本,就构造Android对象,
•••return new Android(setUseSessionTickets, setHostname, trafficStatsTagSocket, trafficStatsUntagSocket, getAlpnSelectedProtocol, setAlpnProtocols);
当然Android是Platform的子类,并且是Platform的内部类。
2,否则就构造Platform对象,
return new Platform();
Android对象的connectSocket方法如下,
try { socket.connect(address, connectTimeout);} catch (SecurityException se) { // Before android 4.3, socket.connect could throw a SecurityException // if opening a socket resulted in an EACCES error. IOException ioException = new IOException("Exception in connect"); ioException.initCause(se); throw ioException;}
其实就是调用socket的connect方法进行连接,如果连接出错则抛出异常。
论述了这么多,本质就是构造Socket对象,并调用Socket对象的connect方法进行连接。
- connect方法分析
- UDP connect 分析
- HTTP CONNECT 方法
- linux connect超时方法
- [QT][源码分析]QObject::connect
- nodejs模块connect源码分析
- nodejs模块connect分析(一)
- [QT][源码分析]QObject::connect
- connect 端口分配源码分析
- [LWIP学习]--connect函数分析
- 抓包分析connect函数
- UDP中的connect方法 和TCP的connect方法详解
- connect设置超时的方法
- 非阻塞connect 编写方法
- react-redux的connect()方法
- [Network]Android N 新wifi connect&auto connect流程分析
- Android Wi-Fi connect & auto connect流程分析(Android 7.0)
- adb connect unable to connect to处理方法
- 添加删除修改
- 渗透测试工具sqlmap基础教程
- C语言里的strcpy()
- 网络安全之VPN详解
- spring中@param和mybatis中@param使用区别
- connect方法分析
- Codeforces 862A Mahmoud and Ehab and the MEX
- POJ3670 Eating Together 【动态规划】【LIS模板】
- spark的几个示例
- java8 不使用循环
- 20170920--navicat测试
- Springboot 整合 Dubbo/ZooKeeper 详解 SOA 案例
- Python函数参数默认值的陷阱和原理深究
- RecycleView刷新加载