tomcat(4)Tomcat的默认连接器
r1)实现 org.apache.catalina.Connector 接口;r2)负责创建实现了 org.apache.catalina.Request接口的request对象;r3)负责创建实现了 org.apache.catalina.Response接口的response对象;
public void invoke(Request request, Response response) // SimpleContainer.invokethrows IOException, ServletException {String servletName = ( (HttpServletRequest) request).getRequestURI();servletName = servletName.substring(servletName.lastIndexOf("/") + 1);URLClassLoader loader = null;try { // 创建类加载器URL[] urls = new URL[1];URLStreamHandler streamHandler = null;File classPath = new File(WEB_ROOT);String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString() ;urls[0] = new URL(null, repository, streamHandler);loader = new URLClassLoader(urls);}catch (IOException e) {System.out.println(e.toString() );}Class myClass = null;try {myClass = loader.loadClass("servlet." + servletName);}catch (ClassNotFoundException e) {System.out.println(e.toString());}Servlet servlet = null;try {servlet = (Servlet) myClass.newInstance(); // 创建请求URI对应的servlet实例 servlet.service((HttpServletRequest) request, (HttpServletResponse) response);}......}
0.3.1)invoke方法内部:servlet容器会载入相应的servlet类,调用其 service() 方法,管理session对象,记录错误消息等操作;0.3.2)Tomcat4的默认连接器使用了一些优化方法:一、使用了一个对象池来避免了频繁创建对象带来的性能损耗;二、在很多地方,Tomcat4 的默认连接器使用了字符数组来代替字符串;(干货——Tomcat4的默认连接器使用了一些优化方法)
I'm as helpless as a kitten up a tree.
那么实际上应该发送如下内容:
1D\r\n
I'm as helpless as a kitten u
9\r\n
p a tree.
0\r\n
1D 的10进制表示是29, 表明第一个块的长度是29个字节,\0\r\n 表明事务已经完成;
Expect: 100-continue //客户端发送
HTTP/1.1 100 continue
//注意,返回内容后面要加上 CRLF 字符。然后server 继续读取输入流的内容。
public final class HttpConnectorimplements Connector, Lifecycle, Runnable {
public final class Bootstrap {public static void main(String[] args) {HttpConnector connector = new HttpConnector();SimpleContainer container = new SimpleContainer();connector.setContainer(container);try {connector.initialize();connector.start();// make the application wait until we press any key.System.in.read();}catch (Exception e) {e.printStackTrace();}}
}
public void initialize() // <span style="font-family: 宋体; font-size: 16px; line-height: 24px;"><strong>HttpConnector.initialize()</strong></span>throws LifecycleException {if (initialized)throw new LifecycleException (sm.getString("httpConnector.alreadyInitialized"));this.initialized=true;Exception eRethrow = null;// Establish a server socket on the specified porttry {serverSocket = open();} catch (IOException ioe) {log("httpConnector, io problem: ", ioe);eRethrow = ioe;} catch (KeyStoreException kse) {log("httpConnector, keystore problem: ", kse);eRethrow = kse;} catch (NoSuchAlgorithmException nsae) {log("httpConnector, keystore algorithm problem: ", nsae);eRethrow = nsae;} catch (CertificateException ce) {log("httpConnector, certificate problem: ", ce);eRethrow = ce;} catch (UnrecoverableKeyException uke) {log("httpConnector, unrecoverable key: ", uke);eRethrow = uke;} catch (KeyManagementException kme) {log("httpConnector, key management problem: ", kme);eRethrow = kme;}if ( eRethrow != null )throw new LifecycleException(threadName + ".open", eRethrow);}
private ServerSocket open() // HttpConnector.open()throws IOException, KeyStoreException, NoSuchAlgorithmException,CertificateException, UnrecoverableKeyException,KeyManagementException{// Acquire the server socket factory for this ConnectorServerSocketFactory factory = getFactory();// If no address is specified, open a connection on all addressesif (address == null) {log(sm.getString("httpConnector.allAddresses"));try {return (factory.createSocket(port, acceptCount));} catch (BindException be) {throw new BindException(be.getMessage() + ":" + port);}}// Open a server socket on the specified addresstry {InetAddress is = InetAddress.getByName(address);log(sm.getString("httpConnector.anAddress", address));try {return (factory.createSocket(port, acceptCount, is));} catch (BindException be) {throw new BindException(be.getMessage() + ":" + address +":" + port);}} catch (Exception e) {log(sm.getString("httpConnector.noAddress", address));try {return (factory.createSocket(port, acceptCount));} catch (BindException be) {throw new BindException(be.getMessage() + ":" + port);}}}
private Stack processors = new Stack(); // HttpConnector.java
void recycle(HttpProcessor processor) { // HttpConnector.java// if (debug >= 2)// log("recycle: Recycling processor " + processor);processors.push(processor);}
private HttpProcessor createProcessor() {synchronized (processors) {if (processors.size() > 0) {// if (debug >= 2)// log("createProcessor: Reusing existing processor");return ((HttpProcessor) processors.pop()); // attend for this line.}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);}}}}
public void start() throws LifecycleException { // HttpConnector.start()// Validate and update our current stateif (started)throw new LifecycleException(sm.getString("httpConnector.alreadyStarted"));threadName = "HttpConnector[" + port + "]";lifecycle.fireLifecycleEvent(START_EVENT, null);started = true;// Start our background threadthreadStart(); // invoke run method.// Create the specified minimum number of processorswhile (curProcessors < minProcessors) {if ((maxProcessors > 0) && (curProcessors >= maxProcessors))break;HttpProcessor processor = newProcessor();recycle(processor);}}
private HttpProcessor newProcessor() { // H<span style="font-family: 宋体;">ttpConnector.newProcessor()</span>// if (debug >= 2)// log("newProcessor: Creating new processor");HttpProcessor processor = new HttpProcessor(this, curProcessors++);if (processor instanceof Lifecycle) {try {((Lifecycle) processor).start();} catch (LifecycleException e) {log("newProcessor", e);return (null);}}created.addElement(processor); // created is a Vector Collection.return (processor);}
private Vector created = new Vector();
void recycle(HttpProcessor processor) { // HttpContainer.recycle()// if (debug >= 2)// log("recycle: Recycling processor " + processor);processors.push(processor);}
public void stop() throws LifecycleException {// Validate and update our current stateif (!started)throw new LifecycleException(sm.getString("httpConnector.notStarted"));lifecycle.fireLifecycleEvent(STOP_EVENT, null);started = false;// Gracefully shut down all processors we have createdfor (int i = created.size() - 1; i >= 0; i--) {HttpProcessor processor = (HttpProcessor) created.elementAt(i); // this line.if (processor instanceof Lifecycle) {try {((Lifecycle) processor).stop();} catch (LifecycleException e) {log("HttpConnector.stop", e);}}}synchronized (threadSync) {// Close the server socket we were usingif (serverSocket != null) {try {serverSocket.close();} catch (IOException e) {;}}// Stop our background threadthreadStop();}serverSocket = null;}
A0)显然变量created是private类型:其在HttpConnector.java 中出现了3次,一次是 private Vector created = new Vector();, 一次是created.addElement(processor);还有一次是stop方法中(上述最后一段代码)(干货——但,HttpProcessor的对象池不是Vector而是Stack);
A1)其中,newProcessor方法负责创建 HttpProcessor 实例,并将 curProcessors 加1;recycle() 方法将创建的HttpProcessor 对象入栈;A2)每个 HttpProcessor 实例负责解析HTTP请求行和请求头, 填充 request对象;void recycle(HttpProcessor processor) { // // if (debug >= 2)// log("recycle: Recycling processor " + processor);processors.push(processor); // <span style="font-weight: bold; font-family: 宋体;">processors is a stack.</span>}
private Stack processors = new Stack(); // HttpConnector.java
public void run() { // HttpConnector.run()// Loop until we receive a shutdown commandwhile (!stopped) {// Accept the next incoming connection from the server socketSocket socket = null;try {// if (debug >= 3)// log("run: Waiting on serverSocket.accept()");socket = serverSocket.accept();// if (debug >= 3)// log("run: Returned from serverSocket.accept()");if (connectionTimeout > 0)socket.setSoTimeout(connectionTimeout);socket.setTcpNoDelay(tcpNoDelay);} catch (AccessControlException ace) {log("socket accept security exception", ace);continue;} catch (IOException e) {// if (debug >= 3)// log("run: Accept returned IOException", e);try {// If reopening fails, exitsynchronized (threadSync) {if (started && !stopped)log("accept error: ", e);if (!stopped) {// if (debug >= 3)// log("run: Closing server socket");serverSocket.close();// if (debug >= 3)// log("run: Reopening server socket");serverSocket = open();}}// if (debug >= 3)// log("run: IOException processing completed");} catch (IOException ioe) {log("socket reopen, io problem: ", ioe);break;} catch (KeyStoreException kse) {log("socket reopen, keystore problem: ", kse);break;} catch (NoSuchAlgorithmException nsae) {log("socket reopen, keystore algorithm problem: ", nsae);break;} catch (CertificateException ce) {log("socket reopen, certificate problem: ", ce);break;} catch (UnrecoverableKeyException uke) {log("socket reopen, unrecoverable key: ", uke);break;} catch (KeyManagementException kme) {log("socket reopen, key management problem: ", kme);break;}continue;}// Hand this socket off to an appropriate processorHttpProcessor processor = createProcessor();if (processor == null) {try {log(sm.getString("httpConnector.noProcessor"));socket.close();} catch (IOException e) {;}continue;}// if (debug >= 3)// log("run: Assigning socket to processor " + processor);processor.assign(socket);// The processor will recycle itself when it finishes}// Notify the threadStop() method that we have shut ourselves down// if (debug >= 3)// log("run: Notifying threadStop() that we have shut down");synchronized (threadSync) {threadSync.notifyAll();}}
HttpProcessor processor = createProcessor(); // invoked by HttpContainer.run() method.
private Stack processors = new Stack(); // you should know the processors is a Stack.
private HttpProcessor createProcessor() { // HttpConnector.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);}}}}<span style="font-family: 宋体;"> </span>
// Hand this socket off to an appropriate processorHttpProcessor processor = createProcessor(); // these code are located in HttpConnector.run() if (processor == null) {try {log(sm.getString("httpConnector.noProcessor"));socket.close();} catch (IOException e) {;}continue;}// if (debug >= 3)// log("run: Assigning socket to processor " + processor);processor.assign(socket); // this line, invoked by HttpConnector.run method.// The processor will recycle itself when it finishes}// Notify the threadStop() method that we have shut ourselves down// if (debug >= 3)// log("run: Notifying threadStop() that we have shut down");synchronized (threadSync) {threadSync.notifyAll();}
synchronized void assign(Socket socket) {// Wait for the Processor to get the previous Socketwhile (available) {try {wait();} catch (InterruptedException e) {}}// Store the newly available Socket and notify our threadthis.socket = socket;available = true;notifyAll();if ((debug >= 1) && (socket != null))log(" An incoming request is being assigned");}
private void process(Socket socket) {boolean ok = true;boolean finishResponse = true;SocketInputStream input = null;OutputStream output = null;// Construct and initialize the objects we will needtry {input = new SocketInputStream(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 requesttry {if (ok) {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);}}} catch (EOFException e) {// It's very likely to be a socket disconnect on either the // client or the serverok = 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 process this requesttry {((HttpServletResponse) response).setHeader("Date", FastHttpDateFormat.getCurrentDate());if (ok) {connector.getContainer().invoke(request, response); // process method invokes the invoke method of corresponding servlet container}} 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 the requestif (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 the connection closure has been requested// by the application or the response stream (in case of HTTP/1.0// and keep-alive).if ( "close".equals(response.getHeader("Connection")) ) {keepAlive = false;}// End of request processingstatus = Constants.PROCESSOR_IDLE;// Recycling the request and the response objectsrequest.recycle();response.recycle();}try {shutdownInput(input);socket.close();} catch (IOException e) {;} catch (Throwable e) {log("process.invoke", e);}socket = null;}
public void run() { // HttpProcessor.run()// Process requests until we receive a shutdown signalwhile (!stopped) {// Wait for the next socket to be assignedSocket socket = await(); // this line, <span style="font-family: 宋体; font-size: 16px; line-height: 24px;">run方法的while循环执行到 await方法时会阻塞</span>if (socket == null)continue;// Process the request from this sockettry {process(socket);} catch (Throwable t) {log("process.invoke", t);}// Finish up this requestconnector.recycle(this);}// Tell threadStop() we have shut ourselves down successfullysynchronized (threadSync) {threadSync.notifyAll();}}
private synchronized Socket await() { // HttpProcessor.await()// Wait for the Connector to provide a new Socketwhile (!available) {try {wait();} catch (InterruptedException e) {}}// Notify the Connector that we have received this SocketSocket socket = this.socket;available = false;notifyAll();if ((debug >= 1) && (socket != null))log(" The incoming request has been awaited");return (socket);}
A1)run方法中的while循环做如下几件事情:获取套接字对象,进行处理,调用连接器的recycle() 方法将当前的 HttpRequest实例压回栈中。A2)下面是 HttpConnector类中 recycle方法的代码:
*/void recycle(HttpProcessor processor) {// if (debug >= 2)// log("recycle: Recycling processor " + processor);processors.push(processor);}
A3)run方法的while循环执行到 await方法时会阻塞。await方法会阻塞处理器线程的控制流,直到它从HttpConnector中获得了新的Socket对象。即,直到HttpConnector对象调用 HttpProcessor实例的assign方法前,都会一直阻塞; 但是,await方法 和assign方法并不是运行在同一个线程中的。assign方法是从 HttpConnector对象的 run方法中调用的。我们称 HttpConnector实例中run方法运行时所在的线程为“连接器线程”。通过使用available的布尔变量和 Object.wait() 方法 和 notifyAll() 方法来进行沟通的;/*** Await a newly assigned Socket from our Connector, or <code>null</code>* if we are supposed to shut down.*/private synchronized Socket await() {// Wait for the Connector to provide a new Socketwhile (!available) {try {wait();} catch (InterruptedException e) {}}// Notify the Connector that we have received this SocketSocket socket = this.socket;available = false;notifyAll();if ((debug >= 1) && (socket != null))log(" The incoming request has been awaited");return (socket);}
A1)wait方法会使当前线程进入等待状态,直到其他线程调用了这个对象的notify() 方法和notifyAll方法;A2)下表总结了 await方法和 assign方法的程序流;
W1)为什么 await方法要使用一个局部变量 socket,而不直接将成员变量socket返回呢? 因为使用局部变量可以在当前Socket对象处理完之前,继续接收下一个Socket对象;W2)为什么 await方法需要调用notifyAll方法呢?是为了防止出现另一个Socket对象以及到达,而此时变量available的值还是true的case。在这种case下,连接器线程会在assign方法内的循环中阻塞,知道处理器线程调用了 notifyAll方法;
【5】Request对象(继承了 RequestBase)
private void process(Socket socket) { // HttpProcessor.process()boolean ok = true;boolean finishResponse = true;SocketInputStream input = null;OutputStream output = null;// Construct and initialize the objects we will needtry {input = new SocketInputStream(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 requesttry {if (ok) {parseConnection(socket); // step1:解析连接parseRequest(input, output); // step2:解析请求if (!request.getRequest().getProtocol() .startsWith("HTTP/0"))parseHeaders(input); // step3:解析请求头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);}}} catch (EOFException e) {// It's very likely to be a socket disconnect on either the // client or the serverok = 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 process this requesttry {((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 the requestif (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 the connection closure has been requested// by the application or the response stream (in case of HTTP/1.0// and keep-alive).if ( "close".equals(response.getHeader("Connection")) ) {keepAlive = false;}// End of request processingstatus = Constants.PROCESSOR_IDLE;// Recycling the request and the response objectsrequest.recycle();response.recycle();}try {shutdownInput(input);socket.close();} catch (IOException e) {;} catch (Throwable e) {log("process.invoke", e);}socket = null;}
// Parse the incoming requesttry { // there code are located in HttpProcessor.process() method.if (ok) {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);}}}
private void parseConnection(Socket socket) // HttpProcessor.parseConnection()throws IOException, ServletException {if (debug >= 2)log(" parseConnection: address=" + socket.getInetAddress() +", port=" + connector.getPort());((HttpRequestImpl) request).setInet(socket.getInetAddress());if (proxyPort != 0)request.setServerPort(proxyPort);elserequest.setServerPort(serverPort);request.setSocket(socket);}
final class DefaultHeaders {// -------------------------------------------------------------- Constantsstatic final char[] AUTHORIZATION_NAME = "authorization".toCharArray();static final char[] ACCEPT_LANGUAGE_NAME = "accept-language".toCharArray();static final char[] COOKIE_NAME = "cookie".toCharArray();static final char[] CONTENT_LENGTH_NAME = "content-length".toCharArray();static final char[] CONTENT_TYPE_NAME = "content-type".toCharArray();static final char[] HOST_NAME = "host".toCharArray();static final char[] CONNECTION_NAME = "connection".toCharArray();static final char[] CONNECTION_CLOSE_VALUE = "close".toCharArray();static final char[] EXPECT_NAME = "expect".toCharArray();static final char[] EXPECT_100_VALUE = "100-continue".toCharArray();static final char[] TRANSFER_ENCODING_NAME ="transfer-encoding".toCharArray();static final HttpHeader CONNECTION_CLOSE =new HttpHeader("connection", "close");static final HttpHeader EXPECT_CONTINUE =new HttpHeader("expect", "100-continue");static final HttpHeader TRANSFER_ENCODING_CHUNKED =new HttpHeader("transfer-encoding", "chunked");
private void parseHeaders(SocketInputStream input) // HttpProcessor.parseHeaders()throws IOException, ServletException {while (true) {HttpHeader header = request.allocateHeader();// Read the next headerinput.readHeader(header);if (header.nameEnd == 0) {if (header.valueEnd == 0) {return;} else {throw new ServletException(sm.getString("httpProcessor.parseHeaders.colon"));}}String value = new String(header.value, 0, header.valueEnd);if (debug >= 1)log(" Header " + new String(header.name, 0, header.nameEnd)+ " = " + value);......request.nextHeader();}}
if (header.nameEnd == 0) {if (header.valueEnd == 0) {return;} else {throw new ServletException(sm.getString("httpProcessor.parseHeaders.colon"));}}
public class SimpleContainer implements Container { // just demonstrate a core method invoke.public void invoke(Request request, Response response)throws IOException, ServletException {String servletName = ( (HttpServletRequest) request).getRequestURI();servletName = servletName.substring(servletName.lastIndexOf("/") + 1);URLClassLoader loader = null;try {URL[] urls = new URL[1];URLStreamHandler streamHandler = null;File classPath = new File(WEB_ROOT);String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString() ;urls[0] = new URL(null, repository, streamHandler);loader = new URLClassLoader(urls);}catch (IOException e) {System.out.println(e.toString() );}Class myClass = null;try {myClass = loader.loadClass("servlet." + servletName);}catch (ClassNotFoundException e) {System.out.println(e.toString());}Servlet servlet = null;try {servlet = (Servlet) myClass.newInstance();servlet.service((HttpServletRequest) request, (HttpServletResponse) response);}catch (Exception e) {System.out.println(e.toString());}catch (Throwable e) {System.out.println(e.toString());}}
/*** Await a newly assigned Socket from our Connector, or <code>null</code>* if we are supposed to shut down.*/private synchronized Socket await() { //HttpProcessor.awati() 方法// Wait for the Connector to provide a new Socketwhile (!available) {try {wait();} catch (InterruptedException e) {}}// Notify the Connector that we have received this SocketSocket socket = this.socket;available = false;notifyAll();if ((debug >= 1) && (socket != null))log(" The incoming request has been awaited");return (socket);}
public final class Bootstrap {public static void main(String[] args) {HttpConnector connector = new HttpConnector();SimpleContainer container = new SimpleContainer(); // 创建容器connector.setContainer(container); // 将该 容器 和 http连接器 相关联try {connector.initialize();connector.start();// make the application wait until we press any key.System.in.read();}catch (Exception e) {e.printStackTrace();}}
}
补充-Complementary ends)
public HttpProcessor(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 + "]";}
public Request createRequest() { HttpRequestImpl request = new HttpRequestImpl();request.setConnector(this);return (request);}
public Response createResponse() {HttpResponseImpl response = new HttpResponseImpl();response.setConnector(this);return (response);}
补充-Complementary2 ends)
E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\src>java -cp .;lib/servlet.jar;lib/catalina_4_1_24.jar;E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\webroot com.tomcat.chapter4.startup.Bootstrap
HttpConnector Opening server socket on all host IP addresses
HttpConnector[8080] Starting background thread
from service
from service
tomcat(4)Tomcat的默认连接器相关推荐
- tomcat默认连接数_Tomcat的默认连接器
tomcat默认连接数 Tomcat有几个连接器可供选择. 我将把APR连接器放在一边,而将重点放在BIO和NIO上. BIO连接器(阻塞I / O)正在阻塞–它使用线程池,每个线程在该线程池中接收请 ...
- Tomcat的默认连接器
Tomcat有几个连接器可供选择. 我将把APR连接器放在一边,而将重点放在BIO和NIO上. BIO连接器(阻塞I / O)正在阻塞–它使用线程池,每个线程在该线程池中接收请求,处理请求,响应并返回 ...
- 聊聊tomcat jdbc pool的默认参数及poolSweeper
序 本文主要研究一下tomcat jdbc pool的默认参数及poolSweeper tomcat jdbc pool 参数默认值 initialSize = 10(默认值) maxActive=1 ...
- 配置了tomcat,更改了默认端口为8070,还是访问不了
配置了tomcat,更改了默认端口为8070,还是访问不了 公司的运维帅哥谁是防火墙没有设置白名单 查看防火墙设置: [root@VDC-032 bin]# iptables -L Chain INP ...
- Tomcat 之 tomcat安装和组件介绍
1 概述 tomcat使用java语言编写,本身自带webser,是一个简装的http server,安装后生产的文件一般放在webapp下对应目录,manager是应用程序管理,tomcat 的站 ...
- 【Tomcat】Tomcat Connector的三种运行模式【bio、nio、apr】
Tomcat Connector(Tomcat连接器)有bio.nio.apr三种运行模式 bio bio(blocking I/O,阻塞式I/O操作),表示Tomcat使用的是传统的Java I/O ...
- Tomcat(一) Tomcat是什么:Tomcat与Java技术 Tomcat与Web应用 以及 Tomcat基本框架及相关配置
Tomcat(一) Tomcat是什么: Tomcat与Java技术 Tomcat与Web应用 以及 Tomcat基本框架及相关配置 Tomcat是一个被广泛使用的Java WEB应用服务器,我们有必 ...
- 【Tomcat 】Tomcat 架构原理解析到架构设计借鉴
Tomcat 发展这么多年,已经比较成熟稳定.在如今『追新求快』的时代,Tomcat 作为 Java Web 开发必备的工具似乎变成了『熟悉的陌生人』,难道说如今就没有必要深入学习它了么?学习它我们又 ...
- 【Tomcat】Tomcat配置与优化(内存、并发、管理)【自己配置】
一.JVM内存配置优化 主要通过以下的几个jvm参数来设置堆内存的: -Xmx512m 最大总堆内存,一般设置为物理内存的1/4 -Xms512m 初始总堆内存,一般将它设置的和最大堆内存一样大,这样 ...
最新文章
- CentOS下的rm命令改造成移动文件至回收站
- 更改应用程序图标_【iOS12人机交互指南】6.2-应用图标
- 无法打开虚拟机“Ubuntu2” (D:\software\Ubuntu2.vmx): 未找到文件。 是否从库中移除“Ubuntu2”?
- 快速运行python虚拟环境_快速入门Python 最新最流行的pipenv虚拟环境
- Vue.js 内部运行机制之总结 常见问题解答
- 腾讯开源业内最大多标签图像数据集,附ResNet-101模型
- centOS中网络配置相关文件配置选项说明
- 信息安全系统设计基础实验三
- wireshark密码嗅探侵入后台管理系统
- java程序是怎么执行的
- 数据库—应用系统开发方法
- 分数换算小数补0法_一年级数学0基础的全过来,最全知识点及基本方法,包你数学不补课都90+...
- 国内移动应用数据安全发展现状
- 企业项目开发中可遵循的时间管理守则-华为时间管理
- 寒風的Cocos2dx之旅之剪刀、石头、布系列专题(2 )
- vertical-align作用,基线详解
- 项目管理工具project软件学习(三) - 自定义日历【6天工作日】/【大小周】
- java 二进制位运算_Java中的二进制与位运算
- windows server 2016 活动目录部署系列(七)活动目录的授权还原
- [山东科技大学OJ]1334 Problem D: 动态的字符串排序
热门文章
- C. Longest Simple Cycle
- 牛客网 【每日一题】6月11日题目精讲 背包
- P5956-[POI2017]Podzielno【数学】
- P5488-差分与前缀和【NTT,生成函数】
- P4254-[JSOI2008]Blue Mary开公司【李超树】
- P4103-[HEOI2014]大工程【虚树,dp】
- P3648-[APIO2014]序列分割【斜率优化】
- ssl2331OJ1373-鱼塘钓鱼 之1【纯贪心】
- CDQ 分治与整体二分
- 2019.01.26【NOIP普及组】模拟赛C组总结