`
javasee
  • 浏览: 958959 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Tomcat NIO源代码分析(三) -- Protocol和Processor

阅读更多

现在请求到了Protocol(Http11NioProtocol)的#process()方法了,由于方法较长,很多代码没有列出:

     public  SocketState process(NioChannel socket)  {
        
//  得到Processor
        Http11NioProcessor processor  =  connections.remove(socket);
        
try   {
            
if  (processor  ==   null {
                processor 
=  recycledProcessors.poll();
            }

            
if  (processor  ==   null {
                processor 
=  createProcessor();
            }


            
//  配置processor是否SSL:略
            ......

            
//  重要:调用Processor的#process()方法
            SocketState state  =  processor.process(socket);

            
//  对长连接的支持:略
             if  (state  ==  SocketState.LONG)  {
                ......
            }

            
if  (state  ==  SocketState.LONG  ||  state  ==  SocketState.ASYNC_END)  {
                
//  Already done all we need to do.
            }
  else   if  (state  ==  SocketState.OPEN)  { //  一般的keep-alive的请求都回到这里
                
//  开始回收Processor
                release(socket);
                
//  如果keep-alive,那么将SocketChannel继续加到Poller中等待
                socket.getPoller().add(socket);
            }
  else   {
                
//  回收Processor
                release(socket);
            }

            
return  state;

        }
  catch (XXXException) {
            
//  略过异常处理
            ......
        }

        
        
//  做一些回收工作
        connections.remove(socket);
        processor.recycle();
        recycledProcessors.offer(processor);
        
return  SocketState.CLOSED;
    }


这里很明显,最重要的是对Processor的#process()的调用,直接上代码,当然,方法太长也略过了很多部分。另外对请求的byte[]的解 析就不上代码了,太长了,主要的方式就是byte[]循环的方式,这也是为了提高效率的考虑,毕竟使用字符串和byte相比还是要慢的。

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

        
//  Setting up the socket
         this .socket  =  socket;
        inputBuffer.setSocket(socket);
        outputBuffer.setSocket(socket);
        inputBuffer.setSelectorPool(endpoint.getSelectorPool());
        outputBuffer.setSelectorPool(endpoint.getSelectorPool());

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

        
long  soTimeout  =  endpoint.getSoTimeout();
        
int  keepAliveTimeout  =  endpoint.getKeepAliveTimeout();

        
boolean  keptAlive  =   false ;
        
boolean  openSocket  =   false ;
        
boolean  recycle  =   true ;
        
final  KeyAttachment ka  =  (KeyAttachment) socket.getAttachment( false );

        
while  ( ! error  &&  keepAlive  &&   ! comet  &&   ! isAsync()  &&   ! endpoint.isPaused())  {
            
//  always default to our soTimeout
            ka.setTimeout(soTimeout);
            
//  Parsing the request header
             try   {
                
if  ( ! disableUploadTimeout  &&  keptAlive  &&  soTimeout  >   0 {
                    socket.getIOChannel().socket().setSoTimeout((
int ) soTimeout);
                }

                
//  这里将Socket的数据读入到读缓冲区,nRead = socket.read(socket.getBufHandler().getReadBuffer());
                
//  并且将协议和请求的URI解析出来
                 if  ( ! inputBuffer.parseRequestLine(keptAlive))  {
                    
//  略过非正常情况的处理
                }

                keptAlive 
=   true ;
                
//  这一步是解析请求的Header,Tomcat的解析是直接基于byte[]去逐个循环的,可以好好学下
                 if  ( ! inputBuffer.parseHeaders())  {
                    
//  略过非正常情况的处理
                }

                request.setStartTime(System.currentTimeMillis());
                
if  ( ! disableUploadTimeout)  {
                    socket.getIOChannel().socket().setSoTimeout(timeout);
                }

            }
  catch (XXXException) {
                
//  略过异常处理
                ......
            }


            
if  ( ! error)  {
                rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
                
try   {
                    
//  设定请求处理的一些Filters
                    prepareRequest();
                }
  catch (XXXException) {
                    
//  略过异常处理
                    ......
                }

            }


            
if  (maxKeepAliveRequests  ==   1 )
                keepAlive 
=   false ;
            
if  (maxKeepAliveRequests  >   0   &&  ka.decrementKeepAlive()  <=   0 )
                keepAlive 
=   false ;

            
//  Process the request in the adapter
             if  ( ! error)  {
                
try   {
                    rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
                    
//  这里就是调用CoyoteAdapter去继续请求了,此时请求会脱离Connctor层进入Engine层了
                    
//  进入Tomcat请求处理PipeLine的下一段管道了
                    adapter.service(request, response);

                    
if  (keepAlive  &&   ! error)  //  Avoid checking twice.
                        error  =  response.getErrorException()  !=   null
                                
||  statusDropsConnection(response.getStatus());
                    }

                    
//  长连接的支持:略
                    ......

                }
  catch (XXXException) {
                    
//  略过异常处理
                    ......
                }

            }


            
//  收尾和回收工作:略

        }
//  while

        rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
        
if  (error  ||  endpoint.isPaused())  {
            recycle();
            
return  SocketState.CLOSED;
        }
  else   if  (comet  ||  isAsync())  {
            
return  SocketState.LONG;
        }
  else   {
            
if  (recycle)  {
                recycle();
            }

            
//  return (openSocket) ? (SocketState.OPEN) : SocketState.CLOSED;
             return  (openSocket)  ?  (recycle  ?  SocketState.OPEN : SocketState.LONG) : SocketState.CLOSED;
        }


    }

 

这段代码有分4个部分需要关注下。
 (1) 对inputBuffer的#parseRequestLine()的调用,这里主要就是读入Socket的数据并且解析出请求的URI;
 (2) 对inputBuffer的#parseHeaders()的调用,这里就是读取请求中的请求头了;
 (3) #prepareRequest()的调用,这里主要是对前两步得到的数据进行分析使用,构建处理请求的上下文属性,并且如果请求的transfer- encoding域有值,需要配置相应的Filter去处理。默认有 IdentityInputFilter,ChunkedInputFilter,VoidInputFilter,BufferedInputFilter 四种;
 (4) 对CoyoteAdapter的#service()的调用,这里就准备进入PipeLine的下一段管道了。

全文完。

分享到:
评论

相关推荐

    xnio-nio-3.8.4.Final-API文档-中英对照版.zip

    赠送源代码:xnio-nio-3.8.4.Final-sources.jar; 赠送Maven依赖信息文件:xnio-nio-3.8.4.Final.pom; 包含翻译后的API文档:xnio-nio-3.8.4.Final-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org....

    xnio-nio-3.8.0.Final-API文档-中文版.zip

    赠送源代码:xnio-nio-3.8.0.Final-sources.jar; 赠送Maven依赖信息文件:xnio-nio-3.8.0.Final.pom; 包含翻译后的API文档:xnio-nio-3.8.0.Final-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.jboss.xnio:...

    xnio-nio-3.8.4.Final-API文档-中文版.zip

    赠送源代码:xnio-nio-3.8.4.Final-sources.jar; 赠送Maven依赖信息文件:xnio-nio-3.8.4.Final.pom; 包含翻译后的API文档:xnio-nio-3.8.4.Final-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.jboss.xnio:...

    xnio-nio-3.8.0.Final-API文档-中英对照版.zip

    赠送源代码:xnio-nio-3.8.0.Final-sources.jar; 赠送Maven依赖信息文件:xnio-nio-3.8.0.Final.pom; 包含翻译后的API文档:xnio-nio-3.8.0.Final-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org....

    httpcore-nio-4.4.15-API文档-中文版.zip

    赠送源代码:httpcore-nio-4.4.15-sources.jar 包含翻译后的API文档:httpcore-nio-4.4.15-javadoc-API文档-中文(简体)版.zip 对应Maven信息:groupId:org.apache.httpcomponents,artifactId:httpcore-nio,...

    Tomcat8源代码

    本文将深入探讨Tomcat 8的源代码,帮助读者理解其工作原理,以便更好地优化和定制自己的服务器环境。 1. **目录结构** Apache Tomcat 8的源代码目录结构清晰,主要分为以下几个部分: - `conf`:存放服务器配置...

    httpcore-nio-4.4.6-API文档-中文版.zip

    赠送源代码:httpcore-nio-4.4.6-sources.jar 包含翻译后的API文档:httpcore-nio-4.4.6-javadoc-API文档-中文(简体)版.zip 对应Maven信息:groupId:org.apache.httpcomponents,artifactId:httpcore-nio,...

    apache-tomcat-8.5.64-windows-x64.zip

    Apache Tomcat 8.5是Java Servlet和JavaServer Pages(JSP)的开源Web应用程序服务器,由Apache软件基金会开发和维护。它是一个轻量级应用服务器,特别适用于部署Java EE Web应用程序。在这个“apache-tomcat-8.5.64...

    tomcat6 源代码

    Apache Tomcat 6是一款广泛应用的开源Java Servlet容器...通过深入学习和研究Tomcat6的源代码,开发者不仅可以掌握Servlet容器的工作原理,还能提升解决实际问题的能力,为构建高效、稳定的Java Web应用打下坚实基础。

    apache-tomcat-7.0.88-src.tar

    在本文中,我们将深入探讨`apache-tomcat-7.0.88-src.tar`这个源代码包,了解其核心组件、工作原理以及如何通过源代码学习和定制Tomcat。 首先,`apache-tomcat-7.0.88-src.tar`是一个包含Apache Tomcat 7.0.88版本...

    apache-tomcat-8.5.97-windows-x.zip

    Apache Tomcat 是一个开源软件应用服务器,主要用于部署和运行Java Servlet和JavaServer Pages(JSP)应用程序。这个压缩包文件 "apache-tomcat-8.5.97-windows-x.zip" 包含了Apache Tomcat 8.5.97 版本在Windows...

    httpcore-nio-4.4.10-API文档-中英对照版.zip

    赠送源代码:httpcore-nio-4.4.10-sources.jar; 赠送Maven依赖信息文件:httpcore-nio-4.4.10.pom; 包含翻译后的API文档:httpcore-nio-4.4.10-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org....

    tomcat7源代码

    《深入剖析Tomcat7源代码》 Tomcat7是一款广泛使用的开源Java Servlet容器,它实现了Java EE中的Web应用规范,包括Servlet、JSP和EL(Expression Language)等。本资源包含Tomcat7的源代码以及运行所需的jar包,...

    httpcore-nio-4.4.15-API文档-中英对照版.zip

    赠送源代码:httpcore-nio-4.4.15-sources.jar 包含翻译后的API文档:httpcore-nio-4.4.15-javadoc-API文档-中文(简体)-英语-对照版.zip 对应Maven信息:groupId:org.apache.httpcomponents,artifactId:...

    tomcat-native-1.2.25-src-build

    "tomcat-native-1.2.25-src-build" 指的是该扩展的源代码版本1.2.25,用于编译生成适用于不同操作系统的本地库文件。 【编译过程】:下载的源码包"tomcat-native-1.2.25-src-build"需要经过编译才能生成适用于目标...

    最新版windows apache-tomcat-9.0.54-windows-x64.zip

    Apache Tomcat是一款开源的Java应用服务器,主要用于运行Java Servlet和JavaServer Pages(JSP)技术。这个最新的版本,即apache-tomcat-9.0.54,是针对Windows操作系统设计的64位版本,提供了在Windows环境下部署和...

    apache-tomcat-9.0.74-windows-x64

    Apache Tomcat 9.0.74 是一个广泛使用的开源软件,它是一个实现了Java Servlet、JavaServer Pages(JSP)和Java EE的Web应用程序容器。这个版本是专门为Windows x64平台设计的,确保在64位操作系统上高效运行。在...

    最新版windows apache-tomcat-9.0.55-windows-x64.zip

    Apache Tomcat是一款开源的Java Servlet容器,主要用于部署和运行Java Web应用程序,包括JSP和Servlet。这个最新的Windows版本,即apache-tomcat-9.0.55-windows-x64.zip,是专为64位Windows操作系统设计的,提供了...

    httpcore-nio-4.4.10-API文档-中文版.zip

    赠送源代码:httpcore-nio-4.4.10-sources.jar; 赠送Maven依赖信息文件:httpcore-nio-4.4.10.pom; 包含翻译后的API文档:httpcore-nio-4.4.10-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.apache....

    Tomcat 8源代码 Servlet源代码

    源代码分析对于理解Tomcat的工作原理、优化性能或进行自定义扩展非常有价值。这里的“简单实用”可能是指通过研究源码,开发者可以更直观地了解Web服务器内部机制,从而更好地应用在实际项目中。 **Tomcat 8源代码...

Global site tag (gtag.js) - Google Analytics