• tomcat源码阅读_代码篇11


    Http11Processor类,该类用于处理接受到得HTTP请求。在该类中主要需要注意的是process方法,如下:

        public void process(Socket socket)
            throws IOException {
            RequestInfo rp = request.getRequestProcessor();
            rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);

            // Set the remote address
            remoteAddr = null;
            remoteHost = null;
            localAddr = null;
            localName = null;
            remotePort = -1;
            localPort = -1;

            // Setting up the I/O
            this.socket = socket;
            inputBuffer.setInputStream(socket.getInputStream());
            outputBuffer.setOutputStream(socket.getOutputStream());

            // Error flag
            error = false;
            keepAlive = true;

            int keepAliveLeft = maxKeepAliveRequests;
            int soTimeout = socket.getSoTimeout();
            int oldSoTimeout = soTimeout;

            int threadRatio = (endpoint.getCurrentThreadsBusy() * 100)
                    / endpoint.getMaxThreads();
            if (threadRatio > 75) {
                keepAliveLeft = 1;
            }
           
            if (soTimeout != oldSoTimeout) {
                try {
                    socket.setSoTimeout(soTimeout);
                } catch (Throwable t) {
                    log.debug(sm.getString("http11processor.socket.timeout"), t);
                    error = true;
                }
            }

            boolean keptAlive = false;

            while (started && !error && keepAlive) {

                // Parsing the request header
                try {
                    if (keptAlive) {
                        if (keepAliveTimeout > 0) {
                            socket.setSoTimeout(keepAliveTimeout);
                        }
                        else if (soTimeout > 0) {
                            socket.setSoTimeout(soTimeout);
                        }
                    }
                    inputBuffer.parseRequestLine();
                    request.setStartTime(System.currentTimeMillis());
                    keptAlive = true;
                    if (!disableUploadTimeout) {
                        socket.setSoTimeout(timeout);
                    }
                    inputBuffer.parseHeaders();
                } catch (IOException e) {
                    error = true;
                    break;
                } catch (Throwable t) {
                    if (log.isDebugEnabled()) {
                        log.debug(sm.getString("http11processor.header.parse"), t);
                    }
                    // 400 - Bad Request
                    response.setStatus(400);
                    error = true;
                }

                if (!error) {
                    // Setting up filters, and parse some request headers
                    rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
                    try {
                        prepareRequest();
                    } catch (Throwable t) {
                        if (log.isDebugEnabled()) {
                            log.debug(sm.getString("http11processor.request.prepare"), t);
                        }
                        // 400 - Internal Server Error
                        response.setStatus(400);
                        error = true;
                    }
                }

                if (maxKeepAliveRequests > 0 && --keepAliveLeft == 0)
                    keepAlive = false;

                // Process the request in the adapter
                if (!error) {
                    try {
                        rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
                        adapter.service(request, response);
                        // Handle when the response was committed before a serious
                        // error occurred. Throwing a ServletException should both
                        // set the status to 500 and set the errorException.
                        // If we fail here, then the response is likely already
                        // committed, so we can't try and set headers.
                        if(keepAlive && !error) { // Avoid checking twice.
                            error = response.getErrorException() != null ||
                                    statusDropsConnection(response.getStatus());
                        }

                    } catch (InterruptedIOException e) {
                        error = true;
                    } catch (Throwable t) {
                        log.error(sm.getString("http11processor.request.process"), t);
                        // 500 - Internal Server Error
                        response.setStatus(500);
                        error = true;
                    }
                }

                // Finish the handling of the request
                try {
                    rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
                    // If we know we are closing the connection, don't drain input.
                    // This way uploading a 100GB file doesn't tie up the thread
                    // if the servlet has rejected it.
                    if(error)
                        inputBuffer.setSwallowInput(false);
                    inputBuffer.endRequest();
                } catch (IOException e) {
                    error = true;
                } catch (Throwable t) {
                    log.error(sm.getString("http11processor.request.finish"), t);
                    // 500 - Internal Server Error
                    response.setStatus(500);
                    error = true;
                }
                try {
                    rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
                    outputBuffer.endRequest();
                } catch (IOException e) {
                    error = true;
                } catch (Throwable t) {
                    log.error(sm.getString("http11processor.response.finish"), t);
                    error = true;
                }

                // If there was an error, make sure the request is counted as
                // and error, and update the statistics counter
                if (error) {
                    response.setStatus(500);
                }
                request.updateCounters();

                rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);

                // Don't reset the param - we'll see it as ended. Next request
                // will reset it
                // thrA.setParam(null);
                // Next request
                inputBuffer.nextRequest();
                outputBuffer.nextRequest();

            }

            rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);

            // Recycle
            inputBuffer.recycle();
            outputBuffer.recycle();
            this.socket = null;
            // Recycle ssl info
            sslSupport = null;
        }

    在该方法中,主要就是完成协议解析,服务,响应等工作。

    1:解析

    inputBuffer.parseRequestLine();

    inputBuffer.parseHeaders();
    prepareRequest();

    2:服务响应

    adapter.service(request, response);

    在上面的语句中使用到了org.apache.catalina.connector.CoyoteAdapter类,该类实现了Adapter接口,用于处理用户请求。

    service方法如下:

        public void service(org.apache.coyote.Request req,
                         org.apache.coyote.Response res)
            throws Exception {

            Request request = (Request) req.getNote(ADAPTER_NOTES);
            Response response = (Response) res.getNote(ADAPTER_NOTES);

            if (request == null) {

                // Create objects
                request = (Request) connector.createRequest();
                request.setCoyoteRequest(req);
                response = (Response) connector.createResponse();
                response.setCoyoteResponse(res);

                // Link objects
                request.setResponse(response);
                response.setRequest(request);

                // Set as notes
                req.setNote(ADAPTER_NOTES, request);
                res.setNote(ADAPTER_NOTES, response);

                // Set query string encoding
                req.getParameters().setQueryStringEncoding
                    (connector.getURIEncoding());

            }

            if (connector.getXpoweredBy()) {
                response.addHeader("X-Powered-By", "Servlet/2.5");
            }

            boolean comet = false;
           
            try {

                // Parse and set Catalina and configuration specific
                // request parameters
                req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());
                if (postParseRequest(req, request, res, response)) {
                    // Calling the container
                    connector.getContainer().getPipeline().getFirst().invoke(request, response);

                    if (request.isComet()) {
                        if (!response.isClosed() && !response.isError()) {
                            if (request.getAvailable() || (request.getContentLength() > 0 && (!request.isParametersParsed()))) {
                                // Invoke a read event right away if there are available bytes
                                if (event(req, res, SocketStatus.OPEN)) {
                                    comet = true;
                                    res.action(ActionCode.ACTION_COMET_BEGIN, null);
                                }
                            } else {
                                comet = true;
                                res.action(ActionCode.ACTION_COMET_BEGIN, null);
                            }
                        } else {
                            // Clear the filter chain, as otherwise it will not be reset elsewhere
                            // since this is a Comet request
                            request.setFilterChain(null);
                        }
                    }

                }

                if (!comet) {
                    response.finishResponse();
                    req.action(ActionCode.ACTION_POST_REQUEST , null);
                }

            } catch (IOException e) {
                ;
            } catch (Throwable t) {
                log.error(sm.getString("coyoteAdapter.service"), t);
            } finally {
                req.getRequestProcessor().setWorkerThreadName(null);
                // Recycle the wrapper request and response
                if (!comet) {
                    request.recycle();
                    response.recycle();

                } else {
                    // Clear converters so that the minimum amount of memory
                    // is used by this processor
                    request.clearEncoders();
                    response.clearEncoders();
                }
            }

        }

    在后边的内容中主要学习

    connector.getContainer().getPipeline().getFirst().invoke(request, response);

    是如何工作的

  • 相关阅读:
    linux下使用g++编译cpp工程
    c++字符串互相转换
    MFC双缓冲绘图实例
    Python进阶之迭代器和生成器
    <大话设计模式>笔记
    配置程序成为Linux服务
    Django的设计模式
    Django ModelForm修改默认的控件属性
    Android活动生命周期
    MySQL必知必会笔记
  • 原文地址:https://www.cnblogs.com/macula7/p/1960473.html
Copyright © 2020-2023  润新知