您的位置:首页 > 理论基础 > 计算机网络

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

2017-09-22 20:09 281 查看
接上一篇:【androidx86 5.1.1】Android HttpClient请求过程解析(上)

4、继续调用HttpRequestExecutor的execute函数,其代码位置位于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();
}
 
7、doReceiveResponse接收响应报文,
/**
    * 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当中进行返回。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: