注:为了单纯的了解连接器运行过程,与别的组件相关部分代码被注释了,该篇文章只是简单的对重点代码进行解释,理论知识可以参考《how tomcat works》这本书,感觉还是不错的。
1.启动(这是自己写的一个简单启动代码)
private static void start() { HttpConnector connector = new HttpConnector(); connector.start(); }
2.HttpConnecter类中的start()方法
public void start() { // Validate and update our current state // if (started) // throw new // LifecycleException(sm.getString("httpConnector.alreadyStarted")); threadName = "HttpConnector[" + port + "]"; // lifecycle.fireLifecycleEvent(START_EVENT, null); started = true; //启动当前线程 threadStart(); // Create the specified minimum number of processors while (curProcessors < minProcessors) { if ((maxProcessors > 0) && (curProcessors >= maxProcessors)) break; HttpProcessor processor = newProcessor(); //将当前线程创建处理器加入处理器池中 recycle(processor); } }
3.HttpConnecter类中threadStart()方法
private void threadStart() { // log(sm.getString("httpConnector.starting")); // 启动当前的connector的线程 thread = new Thread(this, threadName); // 设置为守护线程 thread.setDaemon(true); thread.start(); }
4.HttpConnector类的run()方法
public void run() { // Loop until we receive a shutdown command while (!stopped) { // Accept the next incoming connection from the server socket Socket socket = null; try { socket = serverSocket.accept(); // 设置链接超时(假设设置为10分钟)以后,如果客户端socket和服务端socket链接以后10中以后会自动断开 // tcp链接,默认是一支不设置超时就是一直链接的 if (connectionTimeout > 0) socket.setSoTimeout(connectionTimeout); // 决定是否使用nagle算法,也就是将小数据报先不发送,附加在下一个数据包后面发送过来 socket.setTcpNoDelay(tcpNoDelay); } catch (AccessControlException ace) { log("socket accept security exception", ace); continue; } catch (IOException e) { try { // If reopening fails, exit synchronized (threadSync) { if (started && !stopped) log("accept error: ", e); if (!stopped) { serverSocket.close(); // if (debug >= 3) // log("run: Reopening server socket"); // serverSocket = open(); } } } 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 processor // 启动完一个proccessor线程以后,先让它们处于wait状态,因为此时并没有需要处理的请求。 HttpProcessor processor = createProcessor(); if (processor == null) { try { // log(sm.getString("httpConnector.noProcessor")); socket.close(); } catch (IOException e) { ; } continue; } // 将tcp连接封装的socket对象分配给Processor处理 processor.assign(socket); // The processor will recycle itself when it finishes synchronized (threadSync) { threadSync.notifyAll(); } } }
5.HttpConnector类的assign()方法
synchronized void assign(Socket socket) { // Wait for the Processor to get the previous Socket,默认为false while (available) { try { wait(); } catch (InterruptedException e) { } } // Store the newly available Socket and notify our thread this.socket = socket; //通知processor的线程现在可以启动了 available = true; //通知自己的在等待的线程可以激活了,他们会自己去竞争资源 //因为是用当前processor的对象来进行wait的(),因此就是通知当前processor的线程运行,而不是所有 //在等待processor线程 notifyAll(); if ((debug >= 1) && (socket != null)) log(" An incoming request is being assigned"); }
接下来看看与处理器创建相关代码,因为一个连接器中有可以有多个处理器,因此查看各个处理器创建的过程是很有必要的,这里的多个处理器采用的是处理器池是实现的,跟dbcp数据库连接池的实现方式很相似,接下来看代码
6.httpConnector中createProcessor()方法
注,其中processors的声明是这样的:
private Stack<Object> processors = new Stack<Object>();
private HttpProcessor createProcessor() { synchronized (processors) { // 池中有处理器可用 if (processors.size() > 0) { return ((HttpProcessor) processors.pop()); } // 如果处理器池中没有可以用的处理器,则判断当前的处理器个数(此时池中是空的)是否大于设置最大处理器个数, if ((maxProcessors > 0) && (curProcessors < maxProcessors)) { // 没有则创建 return (newProcessor()); } else { // 如果处理器最大个数被设置为-1,则要多少个处理器就创建多少个,不受限制 if (maxProcessors < 0) { return (newProcessor()); } else { return (null); } } } }
7.httpConnector中newProcessor()方法
private HttpProcessor newProcessor() { // 当创建一个处理器,则当前处理器标记加1,给改处理器设置了个名字,线程也是这么做的 HttpProcessor processor = new HttpProcessor(this, curProcessors++); if (processor instanceof Lifecycle) { try { // 在HttpProcessor类中的start方法里启动processor线程(没创建一个处理器就马上启动,但是启动万以后并没有让processor的run方法马上执行,而是出于wait状态) ((Lifecycle) processor).start(); } catch (Exception e) { log("newProcessor", e); return (null); } } created.addElement(processor); return (processor); }
接下来我们看看HttpProcessor中相关代码
1.HttpProcessor中start()方法
// 基本上都是用在start方法中启动自己的线程的。 public void start() // throws LifecycleException { // if (started) // throw new LifecycleException // (sm.getString("httpProcessor.alreadyStarted")); // lifecycle.fireLifecycleEvent(START_EVENT, null); // started = true; threadStart(); }
2.HttpProcessor中start()方法
private void threadStart() { //log(sm.getString("httpProcessor.starting")); thread = new Thread(this, threadName); //设置为守护线程,因为tomcat是为web应用程序服务的,所以他的线程一般都是守护线程 //同时,在守护线程中创建的线程即使不setDaemon,也是守护线程 thread.setDaemon(true); //开启processor中的run方法。 thread.start(); if (debug >= 1) log(" Background thread has been started"); }
3.HttpProcessor中run()方法
public void run() {
// Process requests until we receive a shutdown signal
while (!stopped) {
//当前线程等待下一个socket来以后激活所有的等等的线程(就是处理器创建以后不马上执行完,而是出于wait状态等待socket来以后并被别的线程激活)
Socket socket = await();
if (socket == null)
continue;
// Process the request from this socket
try {
//该方法就是处理socket,用户解析http头,创建request和response对象(以后会单独详细讲)
process(socket);
} catch (Throwable t) {
log("process.invoke", t);
}
// Finish up this request
connector.recycle(this);
// Tell threadStop() we have shut ourselves down successfully
synchronized (threadSync) {
threadSync.notifyAll();
}
}
4.HttpProcessor中await()方法
private synchronized Socket await() { // Wait for the Connector to provide a new Socket while (!available) { try { //就是调用当前对象的wait()方法 wait(); } catch (InterruptedException e) { } } }
5.HttpProcessor中process()方法
public void process(Socket socket) { //该方法是处理http头和内容的,接下来会详细讲 }
到此,tomcat中连接器的运行过程基本结束了,怎么处理socket会在之后详细讲
相关推荐
6. **连接器与管道**:Coyote连接器负责接收和发送网络数据,管道(Pipeline)则提供了灵活的处理链,允许自定义处理器(Valve)来扩展Tomcat的功能。 7. **部署与热部署**:Tomcat支持自动部署和热部署,只需将WAR...
通过运行源码,我们可以观察到Tomcat的启动过程,这涉及到加载配置、初始化各种组件、注册Servlet和过滤器、以及启动监听器。同时,也可以设置断点,逐步调试,深入理解Tomcat如何处理HTTP请求,如何调用Servlet,...
源码分析是提升开发者对服务器内部运作机制理解的重要途径,尤其对于Tomcat这样的核心组件,源码的学习能够帮助我们更深入地理解Web应用的部署、运行以及性能优化。 首先,我们要了解Tomcat的架构。Tomcat7基于...
本篇文章将深入探讨Tomcat的工作原理,并结合源码进行解析,帮助读者更全面地理解这款服务器的运行机制。 1. **Tomcat架构概述** Tomcat的设计遵循了Servlet容器的基本规范,主要包括四个核心组件:Catalina(核心...
至于文件`tomcat-connectors-1.2.48-src`,这看起来是Tomcat连接器源码的版本,对于开发者来说,研究源码有助于深入理解Tomcat的工作原理,定制连接器功能,或者为Tomcat贡献代码。 总之,Tomcat的连接器是其核心...
源码是软件的基石,通过阅读源码,我们可以了解到Tomcat如何处理HTTP请求,如何管理线程,以及如何部署和运行Web应用。Tomcat的源码主要分为几个核心模块: 1. **Catalina**:这是Tomcat的核心组件,负责Servlet...
Tomcat采用NIO(非阻塞I/O)或BIO(阻塞I/O)模型,Coyote连接器负责这部分实现。NIO模型在高并发环境下表现出色,因为它可以处理大量并发连接,而无需为每个连接创建新线程。 四、Tomcat7的部署与管理 Tomcat7...
7. **连接器(Connector)**:Tomcat支持多种协议,如HTTP/1.1、AJP等。`Coyote`组件负责处理这些协议,其中` CoyoteConnector`是核心部分。 8. **JSP和 Jasper**:Tomcat内置了JSP引擎Jasper,负责编译JSP页面为...
5. **连接器(Connector)与协议处理器(Protocol Handler)** - **Coyote Connector**:Tomcat的Coyote组件负责接收和发送网络数据。它提供了两个协议处理器,JKoyote HTTP/1.1和APR(Apache Portable Runtime)...
再者,Tomcat的连接器(Connector)是处理网络通信的关键部分。在`tomcat-connectors-1.2.37-src.zip`中,我们可以看到对HTTP/1.1协议的支持,包括解析请求、建立响应和管理线程池等。连接器的源码提供了如何实现...
3. **连接器(Connector)**:Tomcat通过连接器与外部世界通信。`connector`目录下的源码展示了如何配置和管理不同的连接器,如基于HTTP/1.1的 Coyote 连接器。 4. **生命周期管理**:在`common`和`shared`目录中,...
Tomcat有多种连接器实现,如 Coyote 和 APR(Apache Portable Runtime),它们在不同的网络协议和性能需求下提供服务。 3. **Jasper**:Jasper是Tomcat中用于处理JSP的组件。它将JSP转换为Java Servlet,然后编译成...
通过阅读和分析源码,开发者可以学习到如何实现一个高效的Servlet容器,如何处理HTTP请求,以及Tomcat是如何管理Web应用程序的部署和运行的。 【压缩包子文件的文件名称列表】"tomcat6-master"可能表示这是Tomcat6...
- `server.xml`:这是Tomcat的主要配置文件,包含了服务、主机、上下文和连接器的配置。 - `web.xml`:每个Web应用都有一个web.xml,它是应用的部署描述符,定义了Servlet、过滤器、监听器等元素。 4. **生命周期...
源码分析部分可能包括Tomcat的启动过程、请求处理流程、线程池管理、容器结构实现以及特定Servlet的生命周期管理等方面。通过阅读源码,开发者可以深入理解Tomcat如何处理网络请求,如何调度线程,以及如何管理和...
- **第3章**:详细解析了Tomcat中的连接器(Connector)组件,它是Tomcat与客户端进行通信的关键部分。 - **第4章**:深入探讨了Tomcat的默认连接器的实现细节,包括HTTP/1.1的新特性及其对连接器的影响。 - **第5章...
### Tomcat7源码手撕过程详解 #### Tomcat初始化流程分析 Tomcat是一个流行的Java Servlet容器,用于部署和运行Web应用程序。理解Tomcat的工作原理对于优化应用性能、解决部署问题至关重要。以下是对Tomcat7启动...
【描述】"Tomcat6的可运行Java源码代码,注意可以运行的哦,只需导入即可"表明这个源码包不仅包含源代码,而且是可运行状态,这意味着开发者可以直接在开发环境中导入这些源码,进行调试、学习或定制化修改。Tomcat6...
Tomcat通过不同的连接器(如HTTP、AJP)与网络通信。`org.apache.coyote`包下包含这些连接器的实现,例如` CoyoteAdapter`、`Http11NioProtocol`等。 5. **部署与生命周期管理**: Tomcat提供自动部署和管理Web...