您的位置:首页 > 理论基础 > 计算机网络

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接收请求关系类图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: