tomcat源码研读笔记—tomcat的接收请求之一 HttpProcessor接收请求
2018-03-22 08:53
423 查看
根据之前的剖析,我们知道tomcat启动好之后,一直在等待这个请求,而这个等待请求的过程就是在HttpConnector的run方法里边,我们可以认为在tomcat启动好之后,就开启了线程在等待着前端发过来的请求:
while (!stopped){
// Accept the next incomingconnection from the server socket
Socket socket = null;
try {
// if (debug >= 3)
// log("run: Waiting onserverSocket.accept()");
socket = serverSocket.accept();
接收到请求之后呢?还是在HttpConnector的run方法里边:
HttpProcessorprocessor = createProcessor();
if (processor == null) {
try {
log(sm.getString("httpConnector.noProcessor"));
socket.close();
} catch (IOException e) {
;
}
continue;
}
// if (debug >= 3)
// log("run: Assigning socketto processor " + processor);
processor.assign(socket);
我们根据代码,进入到createProcessor方法里边查看下:
privateHttpProcessor createProcessor() {
synchronized (processors) {
if (processors.size() > 0) {
// if (debug >= 2)
// log("createProcessor:Reusing existing processor");
return ((HttpProcessor)processors.pop());
}
if ((maxProcessors > 0)&& (curProcessors < maxProcessors)) {
// if (debug >= 2)
// log("createProcessor:Creating new processor");
return (newProcessor());
} else {
if (maxProcessors < 0) {
// if (debug >= 2)
//log("createProcessor: Creating new processor");
return (newProcessor());
} else {
// if (debug >= 2)
//log("createProcessor: Cannot create new processor");
return (null);
}
}
}
}
这里首先对processors的stack栈队进行一个判断,如果存在元素有就弹出一个元素,并对栈队的最大数量进行一些判断,如果没有元素,那么就调用newProcessor创建一个HttpProcessor,我们进入newProcessor方法里边查看下:
privateHttpProcessor newProcessor() {
// if (debug >= 2)
// log("newProcessor: Creatingnew processor");
HttpProcessor processor = newHttpProcessor(this, curProcessors++);
if (processor instanceof Lifecycle) {
try {
((Lifecycle)processor).start();
} catch (LifecycleException e) {
log("newProcessor",e);
return (null);
}
}
created.addElement(processor);
return (processor);
}
可以知道,直接就new了一个HttpProcessor对象出来,但是我们还需要查看下HttpProcessor的构造函数,因里边有一些我们后继需要关注的东西:
publicHttpProcessor(HttpConnector connector, int id) {
super();
this.connector = connector;
this.debug = connector.getDebug();
this.id = id;
this.proxyName = connector.getProxyName();
this.proxyPort =connector.getProxyPort();
this.request = (HttpRequestImpl)connector.createRequest();
this.response = (HttpResponseImpl)connector.createResponse();
this.serverPort = connector.getPort();
this.threadName =
"HttpProcessor[" +connector.getPort() + "][" + id + "]";
}
大家需要注意下,request和response对象的创建,原来调用的是connector的ceatexxx方法,那么我们返回到HttpConnector查看下源码:
public Request createRequest() {
// if (debug >= 2)
// log("createRequest: Creatingnew request");
HttpRequestImpl request = newHttpRequestImpl();
request.setConnector(this);
return (request);
}
public ResponsecreateResponse() {
// if (debug >= 2)
// log("createResponse: Creatingnew response");
HttpResponseImpl response = newHttpResponseImpl();
response.setConnector(this);
return (response);
}
从代码里边我们可以知道其实request指向了它的实现类HttpRequestImpl;response则指向了其实现类HttpResponseImpl
从上述分析我们可以知道,一旦tomcat接收到请求之后,那么就创建了HttpProcessor,并构建了request和response对象
根据HttpConnector的run方法,我们还可以,在创建了HttpProcessor对象之后,tomcat还将发送过来的请求sockect通过assign方法传递给了HttpProcessor:
processor.assign(socket);
我们再深入到HttpProcessor的assign方法源码中:
synchronizedvoid assign(Socket socket) {
// Wait for the Processor to get theprevious Socket
while (available) {
try {
wait();
} catch (InterruptedException e) {
}
}
// Store the newly available Socket andnotify our thread
this.socket = socket;
available = true;
notifyAll();
if ((debug >= 1) && (socket!= null))
log(" An incoming request isbeing assigned");
}
从代码中我们可以知道,原来这里只是对属性进行了一些设置,然后就进行了线程的唤醒,那么根据实现接口Runnable的规律,我们知道,程序将执行run方法,所以:
public voidrun() {
// Process requests until we receive ashutdown signal
while (!stopped) {
// Wait for the next socket to beassigned
Socket socket = await();
if (socket == null)
continue;
// Process the request from thissocket
try {
process(socket);
} catch (Throwable t) {
log("process.invoke",t);
}
// Finish up this request
connector.recycle(this);
}
// Tell threadStop() we have shutourselves down suc
4000
cessfully
synchronized (threadSync) {
threadSync.notifyAll();
}
}
结果有调用了HttpProcessor自己的process方法:
private voidprocess(Socket socket) {
boolean ok = true;
boolean finishResponse = true;
SocketInputStream input = null;
OutputStream output = null;
// Construct and initialize the objectswe will need
try {
input = newSocketInputStream(socket.getInputStream(),
connector.getBufferSize());
} catch (Exception e) {
log("process.create", e);
ok = false;
}
keepAlive = true;
while (!stopped && ok&& keepAlive) {
finishResponse = true;
try {
request.setStream(input);
request.setResponse(response);
output =socket.getOutputStream();
response.setStream(output);
response.setRequest(request);
((HttpServletResponse)response.getResponse()).setHeader
("Server",SERVER_INFO);
} catch (Exception e) {
log("process.create",e);
ok = false;
}
// Parse the incoming request
try {
if (ok) {
parseConnection(socket);
parseRequest(input,output);
if(!request.getRequest().getProtocol()
.startsWith("HTTP/0"))
parseHeaders(input);
if (http11) {
// Sending a requestacknowledge back to the client if
// requested.
ackRequest(output);
// If the protocol isHTTP/1.1, chunking is allowed.
if(connector.isChunkingAllowed())
response.setAllowChunking(true);
}
}
} catch (EOFException e) {
// It's very likely to be asocket disconnect on either the
// client or the server
ok = false;
finishResponse = false;
} catch (ServletException e) {
ok = false;
try {
((HttpServletResponse)response.getResponse())
.sendError(HttpServletResponse.SC_BAD_REQUEST);
} catch (Exception f) {
;
}
} catch (InterruptedIOException e){
if (debug > 1) {
try {
log("process.parse", e);
((HttpServletResponse)response.getResponse())
.sendError(HttpServletResponse.SC_BAD_REQUEST);
} catch (Exception f) {
;
}
}
ok = false;
} catch (Exception e) {
try {
log("process.parse", e);
((HttpServletResponse)response.getResponse()).sendError
(HttpServletResponse.SC_BAD_REQUEST);
} catch (Exception f) {
;
}
ok = false;
}
// Ask our Container to processthis request
try {
((HttpServletResponse)response).setHeader
("Date",FastHttpDateFormat.getCurrentDate());
if (ok) {
connector.getContainer().invoke(request, response);
}
} catch (ServletException e) {
log("process.invoke",e);
try {
((HttpServletResponse)response.getResponse()).sendError
(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (Exception f) {
;
}
ok = false;
} catch (InterruptedIOException e){
ok = false;
} catch (Throwable e) {
log("process.invoke",e);
try {
((HttpServletResponse)response.getResponse()).sendError
(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (Exception f) {
;
}
ok = false;
}
// Finish up the handling of therequest
if (finishResponse) {
try {
response.finishResponse();
} catch (IOException e) {
ok = false;
} catch (Throwable e) {
log("process.invoke", e);
ok = false;
}
try {
request.finishRequest();
} catch (IOException e) {
ok = false;
} catch (Throwable e) {
log("process.invoke",e);
ok = false;
}
try {
if (output != null)
output.flush();
} catch (IOException e) {
ok = false;
}
}
// We have to check if theconnection closure has been requested
// by the application or theresponse stream (in case of HTTP/1.0
// and keep-alive).
if ( "close".equals(response.getHeader("Connection"))) {
keepAlive = false;
}
// End of request processing
status = Constants.PROCESSOR_IDLE;
// Recycling the request and theresponse objects
request.recycle();
response.recycle();
}
我们从代码中查看的时候,只需要注意下面几点:
1, parseConnection(socket);分析链接的端口情况
2, parseRequest(input, output);解析了详细的请求
3, parseHeaders(input);解析了请求头
4, connector.getContainer().invoke(request, response);将请求的信息解析到request和response中,然后调用了容器的invoke方法
我们目前只需要了解这几点,其他细节留待之后慢慢细究!
经过这样剖析,我们就完成了HttpProcessor的请求,我们下边的请求流程图:
HttpProcessor接收请求关系类图:
while (!stopped){
// Accept the next incomingconnection from the server socket
Socket socket = null;
try {
// if (debug >= 3)
// log("run: Waiting onserverSocket.accept()");
socket = serverSocket.accept();
接收到请求之后呢?还是在HttpConnector的run方法里边:
HttpProcessorprocessor = createProcessor();
if (processor == null) {
try {
log(sm.getString("httpConnector.noProcessor"));
socket.close();
} catch (IOException e) {
;
}
continue;
}
// if (debug >= 3)
// log("run: Assigning socketto processor " + processor);
processor.assign(socket);
我们根据代码,进入到createProcessor方法里边查看下:
privateHttpProcessor createProcessor() {
synchronized (processors) {
if (processors.size() > 0) {
// if (debug >= 2)
// log("createProcessor:Reusing existing processor");
return ((HttpProcessor)processors.pop());
}
if ((maxProcessors > 0)&& (curProcessors < maxProcessors)) {
// if (debug >= 2)
// log("createProcessor:Creating new processor");
return (newProcessor());
} else {
if (maxProcessors < 0) {
// if (debug >= 2)
//log("createProcessor: Creating new processor");
return (newProcessor());
} else {
// if (debug >= 2)
//log("createProcessor: Cannot create new processor");
return (null);
}
}
}
}
这里首先对processors的stack栈队进行一个判断,如果存在元素有就弹出一个元素,并对栈队的最大数量进行一些判断,如果没有元素,那么就调用newProcessor创建一个HttpProcessor,我们进入newProcessor方法里边查看下:
privateHttpProcessor newProcessor() {
// if (debug >= 2)
// log("newProcessor: Creatingnew processor");
HttpProcessor processor = newHttpProcessor(this, curProcessors++);
if (processor instanceof Lifecycle) {
try {
((Lifecycle)processor).start();
} catch (LifecycleException e) {
log("newProcessor",e);
return (null);
}
}
created.addElement(processor);
return (processor);
}
可以知道,直接就new了一个HttpProcessor对象出来,但是我们还需要查看下HttpProcessor的构造函数,因里边有一些我们后继需要关注的东西:
publicHttpProcessor(HttpConnector connector, int id) {
super();
this.connector = connector;
this.debug = connector.getDebug();
this.id = id;
this.proxyName = connector.getProxyName();
this.proxyPort =connector.getProxyPort();
this.request = (HttpRequestImpl)connector.createRequest();
this.response = (HttpResponseImpl)connector.createResponse();
this.serverPort = connector.getPort();
this.threadName =
"HttpProcessor[" +connector.getPort() + "][" + id + "]";
}
大家需要注意下,request和response对象的创建,原来调用的是connector的ceatexxx方法,那么我们返回到HttpConnector查看下源码:
public Request createRequest() {
// if (debug >= 2)
// log("createRequest: Creatingnew request");
HttpRequestImpl request = newHttpRequestImpl();
request.setConnector(this);
return (request);
}
public ResponsecreateResponse() {
// if (debug >= 2)
// log("createResponse: Creatingnew response");
HttpResponseImpl response = newHttpResponseImpl();
response.setConnector(this);
return (response);
}
从代码里边我们可以知道其实request指向了它的实现类HttpRequestImpl;response则指向了其实现类HttpResponseImpl
从上述分析我们可以知道,一旦tomcat接收到请求之后,那么就创建了HttpProcessor,并构建了request和response对象
根据HttpConnector的run方法,我们还可以,在创建了HttpProcessor对象之后,tomcat还将发送过来的请求sockect通过assign方法传递给了HttpProcessor:
processor.assign(socket);
我们再深入到HttpProcessor的assign方法源码中:
synchronizedvoid assign(Socket socket) {
// Wait for the Processor to get theprevious Socket
while (available) {
try {
wait();
} catch (InterruptedException e) {
}
}
// Store the newly available Socket andnotify our thread
this.socket = socket;
available = true;
notifyAll();
if ((debug >= 1) && (socket!= null))
log(" An incoming request isbeing assigned");
}
从代码中我们可以知道,原来这里只是对属性进行了一些设置,然后就进行了线程的唤醒,那么根据实现接口Runnable的规律,我们知道,程序将执行run方法,所以:
public voidrun() {
// Process requests until we receive ashutdown signal
while (!stopped) {
// Wait for the next socket to beassigned
Socket socket = await();
if (socket == null)
continue;
// Process the request from thissocket
try {
process(socket);
} catch (Throwable t) {
log("process.invoke",t);
}
// Finish up this request
connector.recycle(this);
}
// Tell threadStop() we have shutourselves down suc
4000
cessfully
synchronized (threadSync) {
threadSync.notifyAll();
}
}
结果有调用了HttpProcessor自己的process方法:
private voidprocess(Socket socket) {
boolean ok = true;
boolean finishResponse = true;
SocketInputStream input = null;
OutputStream output = null;
// Construct and initialize the objectswe will need
try {
input = newSocketInputStream(socket.getInputStream(),
connector.getBufferSize());
} catch (Exception e) {
log("process.create", e);
ok = false;
}
keepAlive = true;
while (!stopped && ok&& keepAlive) {
finishResponse = true;
try {
request.setStream(input);
request.setResponse(response);
output =socket.getOutputStream();
response.setStream(output);
response.setRequest(request);
((HttpServletResponse)response.getResponse()).setHeader
("Server",SERVER_INFO);
} catch (Exception e) {
log("process.create",e);
ok = false;
}
// Parse the incoming request
try {
if (ok) {
parseConnection(socket);
parseRequest(input,output);
if(!request.getRequest().getProtocol()
.startsWith("HTTP/0"))
parseHeaders(input);
if (http11) {
// Sending a requestacknowledge back to the client if
// requested.
ackRequest(output);
// If the protocol isHTTP/1.1, chunking is allowed.
if(connector.isChunkingAllowed())
response.setAllowChunking(true);
}
}
} catch (EOFException e) {
// It's very likely to be asocket disconnect on either the
// client or the server
ok = false;
finishResponse = false;
} catch (ServletException e) {
ok = false;
try {
((HttpServletResponse)response.getResponse())
.sendError(HttpServletResponse.SC_BAD_REQUEST);
} catch (Exception f) {
;
}
} catch (InterruptedIOException e){
if (debug > 1) {
try {
log("process.parse", e);
((HttpServletResponse)response.getResponse())
.sendError(HttpServletResponse.SC_BAD_REQUEST);
} catch (Exception f) {
;
}
}
ok = false;
} catch (Exception e) {
try {
log("process.parse", e);
((HttpServletResponse)response.getResponse()).sendError
(HttpServletResponse.SC_BAD_REQUEST);
} catch (Exception f) {
;
}
ok = false;
}
// Ask our Container to processthis request
try {
((HttpServletResponse)response).setHeader
("Date",FastHttpDateFormat.getCurrentDate());
if (ok) {
connector.getContainer().invoke(request, response);
}
} catch (ServletException e) {
log("process.invoke",e);
try {
((HttpServletResponse)response.getResponse()).sendError
(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (Exception f) {
;
}
ok = false;
} catch (InterruptedIOException e){
ok = false;
} catch (Throwable e) {
log("process.invoke",e);
try {
((HttpServletResponse)response.getResponse()).sendError
(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (Exception f) {
;
}
ok = false;
}
// Finish up the handling of therequest
if (finishResponse) {
try {
response.finishResponse();
} catch (IOException e) {
ok = false;
} catch (Throwable e) {
log("process.invoke", e);
ok = false;
}
try {
request.finishRequest();
} catch (IOException e) {
ok = false;
} catch (Throwable e) {
log("process.invoke",e);
ok = false;
}
try {
if (output != null)
output.flush();
} catch (IOException e) {
ok = false;
}
}
// We have to check if theconnection closure has been requested
// by the application or theresponse stream (in case of HTTP/1.0
// and keep-alive).
if ( "close".equals(response.getHeader("Connection"))) {
keepAlive = false;
}
// End of request processing
status = Constants.PROCESSOR_IDLE;
// Recycling the request and theresponse objects
request.recycle();
response.recycle();
}
我们从代码中查看的时候,只需要注意下面几点:
1, parseConnection(socket);分析链接的端口情况
2, parseRequest(input, output);解析了详细的请求
3, parseHeaders(input);解析了请求头
4, connector.getContainer().invoke(request, response);将请求的信息解析到request和response中,然后调用了容器的invoke方法
我们目前只需要了解这几点,其他细节留待之后慢慢细究!
经过这样剖析,我们就完成了HttpProcessor的请求,我们下边的请求流程图:
HttpProcessor接收请求关系类图:
相关文章推荐
- tomcat源码研读笔记—tomcat的接收请求之三 StandardHost接收请求
- tomcat源码研读笔记—tomcat的接收请求之四 StandardContext接收请求
- tomcat源码研读笔记—tomcat的初始化之三 HttpConnector的初始化
- tomcat源码研读笔记—tomcat的启动之一 StandardServer的启动
- tomcat源码研读笔记—tomcat的启动之二 StandardService的启动
- tomcat源码研读笔记—tomcat的启动之三 StandardEngine的启动
- tomcat源码研读笔记—tomcat的启动之四 StandardHost的启动
- tomcat源码研读笔记—tomcat的启动之五 StandardContext的启动
- tomcat源码研读笔记—tomcat的启动之六 StandardWrapper的启动
- tomcat源码研读笔记—tomcat的启动之七 HttpConnector的启动
- tomcat源码解析(三)--请求过程之数据的接收
- tomcat源码研读笔记—Catalina类
- tomcat源码研读笔记—tomcat的初始化之一 StandardServer的初始化
- tomcat源码研读笔记—tomcat的初始化之二 StandardService的初始化
- tomcat接收到http请求后的处理
- Tomcat源码分析------ 一次完整请求的里里外外
- Tomcat6.0源码学习--接受并传递请求
- tomcat设置可读写,修改tomcat配置可接收get请求中文参数
- 9.2 服务端接收请求消息并发送响应消息源码
- Tomcat7.0.42源码研读概览