隨筆-9  評論-3  文章-0  trackbacks-0
          現在請求到了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的下一段管道了。

          全文完。

          posted on 2010-12-09 09:47 臭美 閱讀(2032) 評論(0)  編輯  收藏 所屬分類: Tomcat
          主站蜘蛛池模板: 灌云县| 宣城市| 修文县| 汉寿县| 杂多县| 达拉特旗| 盐城市| 昭苏县| 宾川县| 吉安市| 乌鲁木齐市| 西吉县| 邓州市| 工布江达县| 南昌市| 株洲县| 库尔勒市| 嵊泗县| 新安县| 吴川市| 务川| 蒲城县| 平武县| 梁河县| 确山县| 卢氏县| 登封市| 江源县| 台湾省| 武鸣县| 辉南县| 民勤县| 邵阳市| 甘南县| 静海县| 江口县| 甘孜| 枝江市| 布拖县| 泉州市| 庆阳市|