彻底掌握网络通信(四)Android源码中HttpClient的发送框架解析

本文详细解析了Android中HttpClient执行HTTP请求的全流程,包括DefaultHttpClient的初始化、DefaultRequestDirector的作用及其实现细节、Socket的创建与连接过程等关键步骤。

网络通信系列文章序

彻底掌握网络通信(一)Http协议基础知识
彻底掌握网络通信(二)Apache的HttpClient基础知识
彻底掌握网络通信(三)Android源码中HttpClient的在不同版本的使用
彻底掌握网络通信(四)Android源码中HttpClient的发送框架解析
彻底掌握网络通信(五)DefaultRequestDirector解析
彻底掌握网络通信(六)HttpRequestRetryHandler解析
彻底掌握网络通信(七)ConnectionReuseStrategy,ConnectionKeepAliveStrategy解析
彻底掌握网络通信(八)AsyncHttpClient源码解读
彻底掌握网络通信(九)AsyncHttpClient为什么无法用Fiddler来抓包
彻底掌握网络通信(十)AsyncHttpClient如何发送JSON解析JSON,以及一些其他用法


前面简单说了下httpclient在不同android版本的配置,这篇主要介绍下Android中HttpClient的执行全流程

1:一图反应http请求的全过程
这里写图片描述

封装给我们展示了强大的能力,把非常复杂的计算封装在方法里面,开发人员只需要简单传入HttpUriRequest参数,便可以实现一次http请求


2:DefaultHttpClient和HttpPost,HttpGet类图
这里写图片描述
2.1)DefaultHttpClient通过方法重载,实现了http发送过程中的很多重要参数
2.2)http请求的方法如post和get,均实现了HttpUriRequest接口,我们可以通过这个类构建httphost参数

3:默认实现的HttpClient一次完成发送的简单步骤描述
3.1)实例化DefaultHttpClient类
3.2)调用父类AbstractHttpClient的execute方法
3.3)父类AbstractHttpClient的execute方法以DefaultHttpClient重载的方法为参数创建DefaultRequestDirector的实例,同时调用DefaultRequestDirector的execute方法完成一次http请求

到这里为止一次http请求还是很粗糙的,http是如何使用socket的,是如何重连,是如何管理连接都没有说到,所以我们要一个步骤一个步骤的细细看,到文章的最后,才会来一个总结性回顾,来说一下一次http连接的完整过程


4: 重要步骤的解析

在实例化DefaultHttpClient的过程中,该类有很多重载方法,其中createClientConnectionManager在默认的httpclient中返回SingleClientConnManager类,这个是贯穿整个重要整个http发送过程中很重要的一个类

4.1)重载方法createClientConnectionManager实现SingleClientConnManager构造

    public SingleClientConnManager(HttpParams params,
                                   SchemeRegistry schreg) {

        if (schreg == null) {
            throw new IllegalArgumentException
                ("Scheme registry must not be null.");
        }
        this.schemeRegistry  = schreg;
        this.connOperator    = createConnectionOperator(schreg);
        this.uniquePoolEntry = new PoolEntry();
        this.managedConn     = null;
        this.lastReleaseTime = -1L;
        this.alwaysShutDown  = false; //@@@ from params? as argument?
        this.isShutDown      = false;

    }

在这个构造函数中,较为重要的成员是ClientConnectionOperator类型的connOperator,PoolEntry类型的uniquePoolEntry 和ConnAdapter类型managedConn ,其中connOperator的默认实现为DefaultClientConnectionOperator,接下来我们看下PoolEntry的构造函数

protected class PoolEntry extends AbstractPoolEntry {

        protected PoolEntry() {
            super(SingleClientConnManager.this.connOperator, null);
        }

在这个构造中传入DefaultClientConnectionOperator,和一个为null的HttpRoute,通过super的方法调用父类AbstractPoolEntry 的构造函数

    protected AbstractPoolEntry(ClientConnectionOperator connOperator,
                                HttpRoute route) {
        super();
        if (connOperator == null) {
            throw new IllegalArgumentException("Connection operator may not be null");
        }
        this.connOperator = connOperator;
        this.connection = connOperator.createConnection();
        this.route = route;
        this.tracker = null;
    }

在这个构造函数中,非常重要的成员是OperatedClientConnection类型的connection,那他的实现者是什么?因为connOperator的实现者为DefaultClientConnectionOperator,那看下他的createConnection方法

    public OperatedClientConnection createConnection() {
        return new DefaultClientConnection();
    }

所以OperatedClientConnection类型的connection的实现者是DefaultClientConnection;

4.2)调用AbstractHttpClient的execute的方法,其最终调用的是DefaultRequestDirector类的execute方法
我们先看下DefaultRequestDirector的构造函数

    //第一个实现者HttpRequestExecutor
    //第二个实现者SingleClientConnManager
    //第三个实现者DefaultConnectionReuseStrategy
    //第四个实现者DefaultConnectionKeepAliveStrategy
    //第五个实现者ProxySelectorRoutePlanner
    //第六个实现者BasicHttpProcessor
    //第七个实现者DefaultHttpRequestRetryHandler
    //第八个实现者DefaultRedirectHandler
    public DefaultRequestDirector(
            final HttpRequestExecutor requestExec,
            final ClientConnectionManager conman,
            final ConnectionReuseStrategy reustrat,
            final ConnectionKeepAliveStrategy kastrat,
            final HttpRoutePlanner rouplan,
            final HttpProcessor httpProcessor,
            final HttpRequestRetryHandler retryHandler,
            final RedirectHandler redirectHandler,
            final AuthenticationHandler targetAuthHandler,
            final AuthenticationHandler proxyAuthHandler,
            final UserTokenHandler userTokenHandler,
            final HttpParams params) {

       /*省略部分代码*/
        this.requestExec       = requestExec;
        this.connManager       = conman;
        this.reuseStrategy     = reustrat;
        this.keepAliveStrategy = kastrat;
        this.routePlanner      = rouplan;
        this.httpProcessor     = httpProcessor;
        this.retryHandler      = retryHandler;
        this.redirectHandler   = redirectHandler;
        this.targetAuthHandler = targetAuthHandler;
        this.proxyAuthHandler  = proxyAuthHandler;
        this.userTokenHandler  = userTokenHandler; 
        this.params            = params;

        this.managedConn       = null;

        this.redirectCount = 0;
        this.maxRedirects = this.params.getIntParameter(ClientPNames.MAX_REDIRECTS, 100);
        this.targetAuthState = new AuthState();
        this.proxyAuthState = new AuthState();
    }

在看下DefaultRequestDirector的execute方法,这个方法比较长,我们先看下managedConn的赋值过程

    public HttpResponse execute(HttpHost target, HttpRequest request,
                                HttpContext context)
        throws HttpException, IOException {
/*省略部分代码*/
ClientConnectionRequest connRequest = connManager.requestConnection(
                            route, userToken);
managedConn = connRequest.getConnection(timeout,TimeUnit.MILLISECONDS);
/*省略部分代码*/       
}

其是通过connManager获得ClientConnectionRequest 对象,在通过该对象调用getConnection方法获得ManagedClientConnection对象managedConn

    public final ClientConnectionRequest requestConnection(
            final HttpRoute route,
            final Object state) {
        //匿名构造
        return new ClientConnectionRequest() {

            public void abortRequest() {
                // Nothing to abort, since requests are immediate.
            }

            public ManagedClientConnection getConnection(
                    long timeout, TimeUnit tunit) {
                return SingleClientConnManager.this.getConnection(
                        route, state);
            }

        };
    }
  public ManagedClientConnection getConnection(HttpRoute route, Object state
  {
  /*省略代码*/
        managedConn = new ConnAdapter(uniquePoolEntry, route);
        return managedConn;
    }

接着我们看下ConnAdapter的构造函数

    protected class ConnAdapter extends AbstractPooledConnAdapter {
        protected ConnAdapter(PoolEntry entry, HttpRoute route) {
            super(SingleClientConnManager.this, entry);
            markReusable();
            entry.route = route;
        }

    }

他会调用父类构造,传入SingleClientConnManager和uniquePoolEntry

最后看下在看下DefaultRequestDirector的execute方法中的发送http逻辑

    public HttpResponse execute(HttpHost target, HttpRequest request,
                                HttpContext context)
        throws HttpException, IOException {
/*省略部分代码*/
    //该类是调用父类AbstractClientConnAdapter的isOpen方法
    //父类的isOpen方法实际调用是PoolEntry父类的AbstractPoolEntry中的OperatedClientConnection connection完成
     if (!managedConn.isOpen()) {
        //调用AbstractPoolEntry的open方法,open方法调用connOperator.openConnection完成socket的创建和连接
         managedConn.open(route, context, params);
      }
/*省略部分代码*/       
}

至此,一次完整的http请求的发送过程中需要的参数基本上都齐了,我们来总结下一次完成的http请求的发送过程
1:DefaultHttpClient重载createClientConnectionManager方法,其默认返回SingleClientConnManager
2:构造SingleClientConnManager的时候,完成成员ClientConnectionOperator connOperator的赋值,其实现者为DefaultClientConnectionOperator;完成成员PoolEntry uniquePoolEntry的赋值
2.1)PoolEntry的构造在其父类AbstractPoolEntry中将ClientConnectionOperator connOperator赋值,其实现者为DefaultClientConnectionOperator;将OperatedClientConnection connection完成赋值,其实现者为DefaultClientConnection
3:最终调用DefaultRequestDirector的execute方法的时候
3.1)调用SingleClientConnManager的requestConnection方法通过匿名内部类的方式获得ClientConnectionRequest实例connRequest
3.2)通过connRequest.getConnection的方法完成对DefaultRequestDirector的成员ManagedClientConnection managedConn的赋值,其实现者为ConnAdapter
3.3)通过managedConn.open方法,经常转换,调用connOperator.openConnection完成socket的创建和连接的
4: 最终通过requestExec.execute的方法完成消息的发送和接收


这个过程还是很抽象的,我们距离例子来形象化

在一个机房中,有很多计算机,一个人,使用遥控器,发送一个按键给某计算机系统,计算机系统内部有一个小的导弹发送模块,导弹发送模块接收到指令,即可把导弹发送出去

在这个例子中
1)使用遥控器我们可以视为实例化DefaultHttpClient的过程
2)点击遥控器发送的按键消息我们可以视为一个HttpPost
3)在这个机房当中,这么多的计算机我们可以通过SingleClientConnManager来进行管理,比如我要关闭所有计算机,获取机房中的一台计算机都可以通过这个类来执行;
一旦有发送导弹的请求,他就会让导弹发送者即ClientConnectionOperator connOperator其默认实现者为DefaultClientConnectionOperator,来发送导弹;那么多的导弹,我们怎么知道要发射什么类型的导弹?所以这里需要一个适配器,他负责创建具体导弹;这里是由ManagedClientConnection managedConn来实现的,其默认实现为ConnAdapter;
4)导弹发射器创建一枚导弹,即通过PoolEntry的DefaultClientConnectionOperator来创建实例OperatedClientConnection connection(我称之为被操作客户端链接),其实现者为DefaultClientConnection
5)最终通过ConnAdapter来实现导弹的寻址和发送的过程

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值