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;}}