读书人

Tomcat NIO源代码分析(3) - Protocol和

发布时间: 2012-09-11 10:49:04 作者: rapoo

Tomcat NIO源代码分析(三) -- Protocol和Processor
现在请求到了Protocol(Http11NioProtocol)的#process()方法了,由于方法较长,很多代码没有列出:

public SocketState process(NioChannel socket) throws IOException {RequestInfo rp = request.getRequestProcessor();rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);// Setting up the socketthis.socket = socket;inputBuffer.setSocket(socket);outputBuffer.setSocket(socket);inputBuffer.setSelectorPool(endpoint.getSelectorPool());outputBuffer.setSelectorPool(endpoint.getSelectorPool());// Error flagerror = 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 soTimeoutka.setTimeout(soTimeout);// Parsing the request headertry {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 {// 设定请求处理的一些FiltersprepareRequest();} catch(XXXException){// 略过异常处理......}}if (maxKeepAliveRequests == 1)keepAlive = false;if (maxKeepAliveRequests > 0 && ka.decrementKeepAlive() <= 0)keepAlive = false;// Process the request in the adapterif (!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){// 略过异常处理......}}// 收尾和回收工作:略}// whilerp.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的下一段管道了。

全文完。 1 楼 fengyonglei 2011-11-07 好文章 谢谢分享

读书人网 >软件架构设计

热点推荐