接上一篇:【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当中进行返回。