/** * Process an incoming HTTP request on the Socket that has been assigned * to this Processor. Any exceptions that occur during processing must be * swallowed and dealt with. * * @param socket The socket on which we are connected to the client */ privatevoidprocess(Socket socket) { booleanok=true; booleanfinishResponse=true; SocketInputStreaminput=null;
// Construct and initialize the objects we will need // 构造对象,这里省略的许多的try-catch input = newSocketInputStream(socket.getInputStream(), connector.getBufferSize()); // Http/1.1中新特性:长连接 keepAlive = true; while (!stopped && ok && keepAlive) { finishResponse = true; request.setStream(input); request.setResponse(response); output = socket.getOutputStream(); response.setStream(output); response.setRequest(request); ((HttpServletResponse) response.getResponse()).setHeader("Server", Constants.ServerInfo); // Parse the incoming request // 解析请求数据 // 解析连接 parseConnection(socket); // 解析请求行 parseRequest(input, output); if (!request.getRequest().getProtocol().startsWith("HTTP/0")) //解析请求头 parseHeaders(input); if (http11) { // Sending a request acknowledge back to the client if // requested. ackRequest(output); // If the protocol is HTTP/1.1, chunking is allowed. if (connector.isChunkingAllowed()) response.setAllowChunking(true); } // Ask our Container to process this request // 调用Servlet容器处理请求 ((HttpServletResponse) response).addDateHeader("Date", System.currentTimeMillis()); connector.getContainer().invoke(request, response); // Finish up the handling of the request response.finishResponse(); request.finishRequest(); // Recycling the request and the response objects // 回收Request、Response对象:把该对象的状态复原使得下一次请求有自己独有的状态 request.recycle(); response.recycle(); } }
publicvoidrun() { // Loop until we receive a shutdown command while (!stopped) { // Accept the next incoming connection from the server socket Socketsocket=null; // Hand this socket off to an appropriate processor // 从池中拿一个HttpProcessor HttpProcessorprocessor= createProcessor(); // 调用HttpProcessor进行处理 processor.assign(socket); } }
publicvoidrun() { // Process requests until we receive a shutdown signal while (!stopped) { // Wait for the next socket to be assigned // 在这里HttpProcessor对象会阻塞直到HttpConnector分配一个socket Socketsocket= await(); if (socket == null) continue; // Process the request from this socket // 进行处理 process(socket); // Finish up this request // 处理完成,把该HttpProcessor放回HttpProcessor对象池中 connector.recycle(this); } }
/** * The socket we are currently processing a request for. This object * is used for inter-thread communication only. */ privateSocketsocket=null; /** * Is there a new socket available? */ privatebooleanavailable=false;
/** * Process an incoming TCP/IP connection on the specified socket. Any * exception that occurs during processing must be logged and swallowed. * NOTE: This method is called from our Connector's thread. We * must assign it to our own thread so that multiple simultaneous * requests can be handled. * * @param socket TCP socket to process */ synchronizedvoidassign(Socket socket) { // Wait for the Processor to get the previous Socket // 如果已经分配,则等待 while (available) { try { wait(); } catch (InterruptedException e) { } } // Store the newly available Socket and notify our thread、 // 分配socket this.socket = socket; available = true; notifyAll(); }
/** * Await a newly assigned Socket from our Connector, or null * if we are supposed to shut down. */ privatesynchronizedSocketawait() { // Wait for the Connector to provide a new Socket // 如果没有分配,则等待 while (!available) { try { wait(); } catch (InterruptedException e) { } } // Notify the Connector that we have received this Socket // 把分配的socket返回 Socketsocket=this.socket; available = false; notifyAll(); return socket; }
/** * The parsed parameters for this request. This is populated only if * parameter information is requested via one of the * getParameter() family of method calls. The key is the * parameter name, while the value is a String array of values for this * parameter. * * IMPLEMENTATION NOTE - Once the parameters for a * particular request are parsed and stored here, they are not modified. * Therefore, application level access to the parameters need not be * synchronized. * 存放Parameter,继承HashMap,与HashMap基本无异 */ protectedParameterMapparameters=null;
/** * Have the parameters for this request been parsed yet? * 是否已经解析 */ protectedbooleanparsed=false;
/** * Parse the parameters of this request, if it has not already occurred. * If parameters are present in both the query string and the request * content, they are merged. */ protectedvoidparseParameters() { if (parsed) return; ParameterMapresults= parameters; // 具体解析逻辑就不给出来了 // Store the final results parsed = true; parameters = results; }
/** * Created by kanyuxia on 2017/4/27. * 模拟org.apache.catalina.Connector接口 */ publicinterfaceConnector { /** * Return the Container used for processing requests received by this * Connector. */ ContainergetContainer();
/** * Set the Container used for processing requests received by this * Connector. * * @param container The new Container to use */ voidsetContainer(Container container);
/** * Return the scheme that will be assigned to requests received * through this connector. Default value is "http". */ StringgetScheme();
/** * Set the scheme that will be assigned to requests received through * this connector. * * @param scheme The new scheme */ voidsetScheme(String scheme);
/** * Create (or allocate) and return a Request object suitable for * specifying the contents of a Request to the responsible Container. */ HttpServletRequestcreateRequest();
/** * Create (or allocate) and return a Response object suitable for * receiving the contents of a Response from the responsible Container. */ HttpServletResponsecreateResponse();
/** * Invoke a pre-startup initialization. This is used to allow connectors * to bind to restricted ports under Unix operating environments. */ voidinitialize();
} /** * Created by kanyuxia on 2017/4/27. * 模拟org.apache.catalina.Container接口 */ publicinterfaceContainer { /** * Process the specified Request, and generate the corresponding Response, * according to the design of this particular Container. * * @param request Request to be processed * @param response Response to be produced * * @exception IOException if an input/output error occurred while * processing * @exception ServletException if a ServletException was thrown * while processing this request */ voidinvoke(HttpRequest request, HttpResponse response)throws IOException, ServletException; }
/** * Created by kanyuxia on 2017/4/26. * Http连接器。 */ publicclassHttpConnectorimplementsRunnable,Connector { /** * The Container used for processing requests received by this Connector. * Servlet容器 */ privateContainercontainer=null;
/** * The current number of processors that have been created. * 当前已经创建的HttpProcessor */ privateintcurProcessors=0;
/** * The minimum number of processors to start at initialization time. * HttpProcessor对象池最小对象数 */ privateintminProcessors=5;
/** * The maximum number of processors allowed, or <0 for unlimited. * HttpProcessor对象池最大对象数 */ privateintmaxProcessors=20;
/** * The port number on which we listen for HTTP requests. * 服务器端口号 */ privateintport=10086;
/** * The set of processors that have been created but are not currently * being used to process a request. * 存放已经创建但未被使用的Http处理器对象 */ privatefinalStack<HttpProcessor> processors=newStack<>();
/** * The set of processors that have ever been created. * 存放已经创建的Http处理器 */ privateVector<HttpProcessor> created=newVector<>();
/** * The request scheme that will be set on all requests received * through this connector. * 服务器处理请求模式(协议) */ privateStringscheme="http";
/** * The server socket through which we listen for incoming TCP connections. * 服务器ServerSocket */ privateServerSocketserverSocket=null;
/** * The background thread that listens for incoming TCP/IP connections and * hands them off to an appropriate processor. * 启动Http连接器,监听Http请求,把socket分发给HttpProcessor进行处理。 */ publicvoidrun() { while (true) { Socketsocket=null; try { socket = serverSocket.accept(); } catch (IOException e) { e.printStackTrace(); } HttpProcessorprocessor= createProcessor(); if (processor != null) { processor.assign(socket); } } }
/** * Create (or allocate) and return an available processor for use in * processing a specific HTTP request, if possible. If the maximum * allowed processors have already been created and are in use, return * <code>null</code> instead. * 创建HttpProcessor:1. 从栈中拿 2. new一个 3. 返回null */ publicHttpProcessorcreateProcessor() { synchronized (processors) { if (processors.size() > 0) { return processors.pop(); } if (maxProcessors > 0 && curProcessors < maxProcessors) { return newProcessor(); } else { if (maxProcessors < 0) { return newProcessor(); } returnnull; } } }
/** * Begin processing requests via this Connector. * 启动Http连接器,并创建HttpProcessor线程对象池 */ publicvoidstart() { // 启动Http连接器 Threadthread=newThread(this); thread.setDaemon(true); thread.start(); // 创建最小HttpProcessor线程对象池 while (curProcessors < minProcessors) { if (maxProcessors > 0 && curProcessors >= maxProcessors) { break; } HttpProcessorprocessor= newProcessor(); recycle(processor); } }
/** * Create and return a new processor suitable for processing HTTP * requests and returning the corresponding responses. * 创建HttpProcessor对象,并使用运行它(它运行在一个单独的后台线程中) */ privateHttpProcessornewProcessor() { HttpProcessorprocessor=newHttpProcessor(this, curProcessors++); created.addElement(processor); processor.start(); return processor; }
/** * Recycle the specified Processor so that it can be used again. * 回收已经没有使用的HttpProcessor * @param processor The processor to be recycled */ voidrecycle(HttpProcessor processor) { processors.push(processor); } }
/** * Created by kanyuxia on 2017/4/26. * Http处理器 */ publicclassHttpProcessorimplementsRunnable {
/** * The HttpConnector with which this processor is associated. */ privateHttpConnectorconnector=null;
/** * Is there a new socket available? * 是否有新的socket可用 */ privatebooleanavailable=false;
/** * The socket we are currently processing a request for. This object * is used for inter-thread communication only. */ privateSocketsocket=null;
/** * The identifier of this processor, unique per connector. */ privateintid=0;
/** * The HTTP request object we will pass to our associated container. */ privateHttpRequesthttpRequest=null;
/** * The HTTP response object we will pass to our associated container. */ privateHttpResponsehttpResponse=null;
/** * Construct a new HttpProcessor associated with the specified connector. * * @param connector HttpConnector that owns this processor * @param id Identifier of this HttpProcessor (unique per connector) */ publicHttpProcessor(HttpConnector connector, int id) { this.connector = connector; this.id = id; this.httpRequest = (HttpRequest) connector.createRequest(); this.httpResponse = (HttpResponse) connector.createResponse(); }
/** * Start the background thread we will use for request processing. * 启动一个后台线程运行HttpProcessor */ publicvoidstart() { Threadthread=newThread(this); thread.setDaemon(true); thread.start(); }
/** * The background thread that listens for incoming TCP/IP connections and * hands them off to an appropriate processor. * 等待HttpConnector分配socket,然后处理该scoket,最后通知HttpConnector回收该HttpProcessor */ publicvoidrun() { while (true) { // Wait for the next socket to be assigned Socketsocket= await(); if (socket == null) { continue; } System.out.println(Thread.currentThread().getName()); // Process the request from this socket process(socket);
// Finish up this request connector.recycle(this); } }
/** * Process an incoming HTTP request on the Socket that has been assigned * to this Processor. Any exceptions that occur during processing must be * swallowed and dealt with. * 处理HttpConector分配的socket:1. 解析请求 2. 处理请求(调用容器处理) * @param socket The socket on which we are connected to the client */ privatevoidprocess(Socket socket) { InputStreaminput=null; OutputStreamoutput=null; try { input = socket.getInputStream(); output = socket.getOutputStream(); } catch (IOException e) { e.printStackTrace(); } httpRequest.setInput(input); httpResponse.setOutput(output); httpResponse.setHttpRequest(httpRequest); // Parse the incoming request parseConnection(socket); parseRequest(input, output); parseHeader(input, output);
// Ask our Container to process this request try { connector.getContainer().invoke(httpRequest, httpResponse); } catch (IOException e) { e.printStackTrace(); } catch (ServletException e) { e.printStackTrace(); }
/** * Parse and record the connection parameters related to this request. * 解析连接 * @param socket The socket on which we are connected */ privatevoidparseConnection(Socket socket) { }
/** * Parse the incoming HTTP request and set the corresponding HTTP request * properties. * 解析请求行 * @param input The input stream attached to our socket * @param output The output stream of the socket */ privatevoidparseRequest(InputStream input, OutputStream output) { // 在这里仅仅解析了requestURI BufferedInputStreaminputStream=newBufferedInputStream(input); StringBuilderstringBuilder=newStringBuilder(1024); byte[] buffer=newbyte[1024]; intb=0; try { b = inputStream.read(buffer); } catch (IOException e) { e.printStackTrace(); } for (inti=0; i < b; i++) { stringBuilder.append((char) buffer[i]); } intbegin= stringBuilder.indexOf(" ") + 1; intend= stringBuilder.indexOf(" ", begin); StringrequestURI= stringBuilder.substring(begin, end); httpRequest.setRequestURI(requestURI); }
/** * Process an incoming TCP/IP connection on the specified socket. Any * exception that occurs during processing must be logged and swallowed. * <b>NOTE</b>: This method is called from our Connector's thread. We * must assign it to our own thread so that multiple simultaneous * requests can be handled. * HttpConnector分配一个新的socket * @param socket TCP socket to process */ publicvoidassign(Socket socket) { synchronized (this) { // Wait for the Processor to get the previous Socket while (available) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } }
// Store the newly available Socket and notify our thread this.socket = socket; available = true; notifyAll(); } }
/** * Await a newly assigned Socket from our Connector, or <code>null</code> * if we are supposed to shut down. * 等待HttpConenctor分配一个新的socket */ privateSocketawait() { synchronized (this) { // Wait for the Connector to provide a new Socket while (!available) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } }
// Notify the Connector that we have received this Socket available = false; notifyAll(); return socket; } } }