【androidx86 5.1.1】Android HttpClient请求过程解析(下)

接上一篇:【androidx86 5.1.1】Android HttpClient请求过程解析(上)


4、继续调用HttpRequestExecutorexecute函数,其代码位置位于external\apache-http\src\org\apache\http\protocol\HttpRequestExecutor.java

/**

    * Synchronously send a request and obtain the response.

    *

    * @param request  the request tosend. It will be preprocessed.

    * @param conn     the openconnection over which to send

    *

    * @return the response to therequest, postprocessed

    *

    * @throws HttpException     incase of a protocol or processing problem

    * @throws IOException       incase of an I/O problem

    */   

   public HttpResponse execute(

           final HttpRequest request,

           final HttpClientConnection conn,

           final HttpContext context)

               throws IOException,HttpException {

       if (request == null) {

           throw new IllegalArgumentException("HTTP request may not benull");

       }

       if (conn == null) {

           throw new IllegalArgumentException("Client connection may not benull");

       }

       if (context == null) {

           throw new IllegalArgumentException("HTTP context may not benull");

       }

 

       try {

                    //通过doSendRequest函数发送请求,发送成功返回null

           HttpResponse response = doSendRequest(request, conn, context);

           if (response == null) {

                           //发送成功则接受数据

               response =doReceiveResponse(request, conn, context);

           }

           return response;

       } catch (IOException ex) {

           conn.close();

           throw ex;

       } catch (HttpException ex) {

           conn.close();

           throw ex;

       } catch (RuntimeException ex) {

           conn.close();

           throw ex;

       }

}

 

5、接下来通过doSendRequest发送请求,总体作用是判断连接情况,其源代码位于external\apache-http\src\org\apache\http\protocol\HttpRequestExecutor.java

      /**

    * Send a request over a connection.

    * This method also handles the expect-continue handshake if necessary.

    * If it does not have to handle an expect-continue handshake, it will

    * not use the connection for reading or anything else that depends on

    * data coming in over the connection.

    *

    * @param request  the request tosend, already

    *                 {@link #preProcesspreprocessed}

    * @param conn     the connectionover which to send the request,

    *                 alreadyestablished

    * @param context  the context forsending the request

    *

    * @return a terminal responsereceived as part of an expect-continue

    *         handshake, or

    *         <code>null</code> if the expect-continue handshake is notused

    *

    * @throws HttpException     incase of a protocol or processing problem

    * @throws IOException       incase of an I/O problem

    */

   protected HttpResponse doSendRequest(

           final HttpRequest request,

           final HttpClientConnection conn,

           final HttpContext context)

               throws IOException,HttpException {

       if (request == null) {

           throw new IllegalArgumentException("HTTP request may not benull");

       }

       if (conn == null) {

           throw new IllegalArgumentException("HTTP connection may not benull");

       }

       if (context == null) {

           throw new IllegalArgumentException("HTTP context may not benull");

       }

 

       HttpResponse response = null;

       context.setAttribute(ExecutionContext.HTTP_REQ_SENT, Boolean.FALSE);

 

             //发送http首部

       conn.sendRequestHeader(request);

       if (request instanceof HttpEntityEnclosingRequest) {

           // Check for expect-continue handshake. We have to flush the

           // headers and wait for an 100-continue response to handle it.

           // If we get a different response, we must not send the entity.

           boolean sendentity = true;

           final ProtocolVersion ver =

               request.getRequestLine().getProtocolVersion();

           if (((HttpEntityEnclosingRequest) request).expectContinue() &&

               !ver.lessEquals(HttpVersion.HTTP_1_0)) {

 

               conn.flush();

               // As suggested by RFC 2616section 8.2.3, we don't wait for a

               // 100-continue responseforever. On timeout, send the entity.

               int tms =request.getParams().getIntParameter(

                       CoreProtocolPNames.WAIT_FOR_CONTINUE, 2000);

               //判断服务端对于连接中的数据状态是否正常

               if(conn.isResponseAvailable(tms)) {

                   response =conn.receiveResponseHeader();

                   if(canResponseHaveBody(request, response)) {

                       conn.receiveResponseEntity(response);

                   }

                   int status = response.getStatusLine().getStatusCode();

                   if (status < 200) {

                       if (status !=HttpStatus.SC_CONTINUE) {

                           throw newProtocolException(

                                   "Unexpected response: " + response.getStatusLine());

                       }

                       // discard 100-continue

                       response = null;

                   } else {

                       sendentity = false;

                   }

               }

           }

                    //如果数据状态正确,则发送内容

           if (sendentity) {

               conn.sendRequestEntity((HttpEntityEnclosingRequest) request);

           }

       }

       conn.flush();

       context.setAttribute(ExecutionContext.HTTP_REQ_SENT, Boolean.TRUE);

       return response;

}

总体来说分为三步,第一步,发送请求行并获取状态行;第二步,判断连接状态;第三步,发送实体。

6、然后通过EntitySerializer.java中的serialize方法进行发送,对应代码位于src\org\apache\http\impl\entity\EntitySerializer.java

public void serialize(

           final SessionOutputBuffer outbuffer,

           final HttpMessage message,

           final HttpEntity entity) throws HttpException, IOException {

       if (outbuffer == null) {

           throw new IllegalArgumentException("Session output buffer may notbe null");

       }

       if (message == null) {

           throw new IllegalArgumentException("HTTP message may not benull");

       }

       if (entity == null) {

           throw new IllegalArgumentException("HTTP entity may not benull");

       }

       OutputStream outstream = doSerialize(outbuffer, message);

       entity.writeTo(outstream);

       outstream.close();

}

 

7doReceiveResponse接收响应报文,

/**

    * Wait for and receive a response.

    * This method will automatically ignore intermediate responses

    * with status code 1xx.

    *

    * @param request  the request forwhich to obtain the response

    * @param conn     the connectionover which the request was sent

    * @param context  the context forreceiving the response

    *

    * @return the final response, notyet post-processed

    *

    * @throws HttpException     incase of a protocol or processing problem

    * @throws IOException       incase of an I/O problem

    */

   protected HttpResponse doReceiveResponse(

           final HttpRequest         request,

           final HttpClientConnection conn,

           final HttpContext         context)

               throws HttpException,IOException {

             //异常判断

       if (request == null) {

           throw new IllegalArgumentException("HTTP request may not benull");

       }

       if (conn == null) {

           throw new IllegalArgumentException("HTTP connection may not benull");

       }

       if (context == null) {

           throw new IllegalArgumentException("HTTP context may not benull");

       }

 

       HttpResponse response = null;

       int statuscode = 0;

             

            //循环读取返回状态以及响应报文

       while (response == null || statuscode < HttpStatus.SC_OK) {

 

           response = conn.receiveResponseHeader();

           if (canResponseHaveBody(request, response)) {

               conn.receiveResponseEntity(response);

           }

           statuscode = response.getStatusLine().getStatusCode();

 

       } // while intermediate response

 

       return response;

 

}

最后,通过死循环,在statu表明连接正常的情况下不断读取响应报文,读取成功则存储到reponse当中进行返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值