现在请求到了Protocol(Http11NioProtocol)的#process()方法了,由于方法较长,很多代码没有列出:

public
SocketState process(NioChannel socket)
{
//
得到Processor
Http11NioProcessor processor
=
connections.remove(socket);
try
{
if
(processor
==
null
)
{
processor
=
recycledProcessors.poll();
}

if
(processor
==
null
)
{
processor
=
createProcessor();
}

//
配置processor是否SSL:略
......
//
重要:调用Processor的#process()方法
SocketState state
=
processor.process(socket);
//
对长连接的支持:略

if
(state
==
SocketState.LONG)
{
......
}

if
(state
==
SocketState.LONG
||
state
==
SocketState.ASYNC_END)
{
//
Already done all we need to do.

}
else
if
(state
==
SocketState.OPEN)
{
//
一般的keep-alive的请求都回到这里
//
开始回收Processor
release(socket);
//
如果keep-alive,那么将SocketChannel继续加到Poller中等待
socket.getPoller().add(socket);
}
else
{
//
回收Processor
release(socket);
}
return
state;

}
catch
(XXXException)
{
//
略过异常处理
......
}
//
做一些回收工作
connections.remove(socket);
processor.recycle();
recycledProcessors.offer(processor);
return
SocketState.CLOSED;
}
这里很明显,最重要的是对Processor的#process()的调用,直接上代码,当然,方法太长也略过了很多部分。另外对请求的byte[]的解
析就不上代码了,太长了,主要的方式就是byte[]循环的方式,这也是为了提高效率的考虑,毕竟使用字符串和byte相比还是要慢的。

public
SocketState process(NioChannel socket)
throws
IOException
{
RequestInfo rp
=
request.getRequestProcessor();
rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
//
Setting up the socket
this
.socket
=
socket;
inputBuffer.setSocket(socket);
outputBuffer.setSocket(socket);
inputBuffer.setSelectorPool(endpoint.getSelectorPool());
outputBuffer.setSelectorPool(endpoint.getSelectorPool());
//
Error flag
error
=
false
;
keepAlive
=
true
;
comet
=
false
;
long
soTimeout
=
endpoint.getSoTimeout();
int
keepAliveTimeout
=
endpoint.getKeepAliveTimeout();
boolean
keptAlive
=
false
;
boolean
openSocket
=
false
;
boolean
recycle
=
true
;
final
KeyAttachment ka
=
(KeyAttachment) socket.getAttachment(
false
);

while
(
!
error
&&
keepAlive
&&
!
comet
&&
!
isAsync()
&&
!
endpoint.isPaused())
{
//
always default to our soTimeout
ka.setTimeout(soTimeout);
//
Parsing the request header

try
{
if
(
!
disableUploadTimeout
&&
keptAlive
&&
soTimeout
>
0
)
{
socket.getIOChannel().socket().setSoTimeout((
int
) soTimeout);
}
//
这里将Socket的数据读入到读缓冲区,nRead = socket.read(socket.getBufHandler().getReadBuffer());
//
并且将协议和请求的URI解析出来

if
(
!
inputBuffer.parseRequestLine(keptAlive))
{
//
略过非正常情况的处理
}
keptAlive
=
true
;
//
这一步是解析请求的Header,Tomcat的解析是直接基于byte[]去逐个循环的,可以好好学下

if
(
!
inputBuffer.parseHeaders())
{
//
略过非正常情况的处理
}
request.setStartTime(System.currentTimeMillis());
if
(
!
disableUploadTimeout)
{
socket.getIOChannel().socket().setSoTimeout(timeout);
}

}
catch
(XXXException)
{
//
略过异常处理
......
}


if
(
!
error)
{
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
try
{
//
设定请求处理的一些Filters
prepareRequest();
}
catch
(XXXException)
{
//
略过异常处理
......
}
}

if
(maxKeepAliveRequests
==
1
)
keepAlive
=
false
;
if
(maxKeepAliveRequests
>
0
&&
ka.decrementKeepAlive()
<=
0
)
keepAlive
=
false
;
//
Process the request in the adapter

if
(
!
error)
{
try
{
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
//
这里就是调用CoyoteAdapter去继续请求了,此时请求会脱离Connctor层进入Engine层了
//
进入Tomcat请求处理PipeLine的下一段管道了
adapter.service(request, response);

if
(keepAlive
&&
!
error)
{
//
Avoid checking twice.
error
=
response.getErrorException()
!=
null
||
statusDropsConnection(response.getStatus());
}
//
长连接的支持:略
......

}
catch
(XXXException)
{
//
略过异常处理
......
}
}

//
收尾和回收工作:略
}
//
while
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
if
(error
||
endpoint.isPaused())
{
recycle();
return
SocketState.CLOSED;
}
else
if
(comet
||
isAsync())
{
return
SocketState.LONG;
}
else
{
if
(recycle)
{
recycle();
}
//
return (openSocket) ? (SocketState.OPEN) : SocketState.CLOSED;
return
(openSocket)
?
(recycle
?
SocketState.OPEN : SocketState.LONG) : SocketState.CLOSED;
}

}
这段代码有分4个部分需要关注下。
(1) 对inputBuffer的#parseRequestLine()的调用,这里主要就是读入Socket的数据并且解析出请求的URI;
(2) 对inputBuffer的#parseHeaders()的调用,这里就是读取请求中的请求头了;
(3)
#prepareRequest()的调用,这里主要是对前两步得到的数据进行分析使用,构建处理请求的上下文属性,并且如果请求的transfer-
encoding域有值,需要配置相应的Filter去处理。默认有
IdentityInputFilter,ChunkedInputFilter,VoidInputFilter,BufferedInputFilter
四种;
(4) 对CoyoteAdapter的#service()的调用,这里就准备进入PipeLine的下一段管道了。
全文完。
565

被折叠的 条评论
为什么被折叠?



