亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

How Tomcat Works(二)

系統 1841 0

我們這些可憐蟲,只有沿著大神的思路,這樣我們才能進步得更快;因為我們不是跟大神處于同一級別上。所以我這里是參考《How Tomcat Works》這本英文版的大作來理解tomcat的工作原理

本人認為,Tomcat容器源碼是學習java編程以及設計模式等的絕佳范例,深入理解其源碼對我輩開發人員的編程水平提高大有裨益!

我們可以從該書指定的官方網址下載相關示例源碼 http://www.brainysoftware.com,本文順著作者的思路,介紹一個簡單的web服務器

我們知道,web服務器是使用http協議與客戶端進行通信,所以讀者有必要先了解http協議格式;基于java的web服務器會使用兩個重要的類 java.net.Socket與java.net.ServerSocket(服務器端與客戶端通過Socket通信)

關于http協議,網上的資料汗牛充棟,本人在這里加上簡略的描述(http協議基于tcp協議)

http客戶端請求包括如下部分:

Method-URI-Protocol/Version 方法-地址-版本
Request header 請求頭
Entity body 請求實體

比如 http://www.outletss.com/ ?是本人以前幫客戶做的網站,如果我們在瀏覽器打開該url地址,實際上客戶端向服務器發送了如下格式的消息

      GET http://www.outletss.com/ HTTP/1.1
      
        
Host: www.outletss.com
Connection: keep-alive
Accept: text/html
      
      ,application/xhtml+xml,application/xml
      
        ;
      
      
        q=0.9,*/*;q=0.8
      
      
User-Agent: Mozilla/5.0 (Windows NT 5.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36
      
        
Accept-Encoding: gzip
      
      ,deflate,
      
        sdch
Accept-Language: zh-CN
      
      ,zh
      
        ;
      
      
        q=0.8
      
      
Cookie: lzstat_uv=12863370662865423613|2989608
      
        ;
      
      
         CKFinder_Path=Images%3A%2F%3A1; JSESSIONID=D7F9EC74149CB674D19A253B46273A77; lzstat_ss=1366758708_0_1375562495_2989608
      
    

http服務器端響應包括如下部分:

Protocol-Status code-Description 協議狀態 描述代碼
Response headers 響應頭
Entity body 響應實體

然后服務器端向客戶端響應了如下格式的消息

      HTTP/1.1 200
      
         OK
Connection: close
Date: Sat
      
      , 03 Aug 2013 15:00:30
      
         GMT
Server: Microsoft-IIS/
      
      6.0
      
        
X-UA-Compatible: IE
      
      =
      
        EmulateIE7
X-Powered-By: ASP.NET
Set-Cookie: JSESSIONID
      
      =0A5B07FF5661CA6F8D87937A54B4EEF5
      
        ;
      
      
         Path=/; HttpOnly
      
      
Content-Type: text/html
      
        ;
      
      
        charset=UTF-8
      
      
        Content-Language: zh-CN






<!DOCTYPE html PUBLIC 
      
      "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
      
        >
<html xmlns
      
      ="http://www.w3.org/1999/xhtml"
      
        >
//這里省略了html代碼
</html>
      
    

基于java的Socket編程,可以參考java網絡編程相關資料,Socket服務器端與客戶端的網絡交互與本地文件系統I/O具有一致的編程模型,基本上也是輸入流與輸出流的概念(如果你不懂輸入流輸出流的概念,基本上還要去修煉)

Socket分為客戶端與服務器端,Socket表示客戶端套接字,ServerSocket表示服務器端套接字,我們參考書中示例,看一個簡單的服務器怎么實現

HttpServer類表示一個web服務器,示例代碼如下:

      
        public
      
      
        class
      
      
         HttpServer {

  
      
      
        /**
      
      
         WEB_ROOT is the directory where our HTML and other files reside.
   *  For this package, WEB_ROOT is the "webroot" directory under the working
   *  directory.
   *  The working directory is the location in the file system
   *  from where the java command was invoked.
   
      
      
        */
      
      
        public
      
      
        static
      
      
        final
      
       String WEB_ROOT =
      
        
    System.getProperty(
      
      "user.dir") + File.separator  + "webroot"
      
        ;

  
      
      
        //
      
      
         shutdown command
      
      
        private
      
      
        static
      
      
        final
      
       String SHUTDOWN_COMMAND = "/SHUTDOWN"
      
        ;

  
      
      
        //
      
      
         the shutdown command received
      
      
        private
      
      
        boolean
      
       shutdown = 
      
        false
      
      
        ;

  
      
      
        public
      
      
        static
      
      
        void
      
      
         main(String[] args) {
    HttpServer server 
      
      = 
      
        new
      
      
         HttpServer();
    server.await();
  }

  
      
      
        public
      
      
        void
      
      
         await() {
    ServerSocket serverSocket 
      
      = 
      
        null
      
      
        ;
    
      
      
        int
      
       port = 8080
      
        ;
    
      
      
        try
      
      
         {
      serverSocket 
      
      =  
      
        new
      
       ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"
      
        ));
    }
    
      
      
        catch
      
      
         (IOException e) {
      e.printStackTrace();
      System.exit(
      
      1
      
        );
    }

    
      
      
        //
      
      
         Loop waiting for a request
      
      
        while
      
       (!
      
        shutdown) {
      Socket socket 
      
      = 
      
        null
      
      
        ;
      InputStream input 
      
      = 
      
        null
      
      
        ;
      OutputStream output 
      
      = 
      
        null
      
      
        ;
      
      
      
        try
      
      
         {
        socket 
      
      =
      
         serverSocket.accept();
        input 
      
      =
      
         socket.getInputStream();
        output 
      
      =
      
         socket.getOutputStream();

        
      
      
        //
      
      
         create Request object and parse
      
      
        Request request = 
      
        new
      
      
         Request(input);
        request.parse();

        
      
      
        //
      
      
         create Response object
      
      
        Response response = 
      
        new
      
      
         Response(output);
        response.setRequest(request);
        response.sendStaticResource();

        
      
      
        //
      
      
         Close the socket
      
      
                socket.close();

        
      
      
        //
      
      
        check if the previous URI is a shutdown command
      
      
        shutdown =
      
         request.getUri().equals(SHUTDOWN_COMMAND);
      }
      
      
      
        catch
      
      
         (Exception e) {
        e.printStackTrace();
        
      
      
        continue
      
      
        ;
      }
    }
  }
}
      
    

在上面代碼里面,首先創建一個ServerSocket實例,然后用一個while循環監聽客戶端請求,接收到客戶端請求后,通過ServerSocket實例的accept方法返回Socket實例,將該Socket實例的輸入流與輸出流封裝成Request實例與Response實例,并調用Response實例的void sendStaticResource()方法響應請求。

Request類代碼如下:

      
        public
      
      
        class
      
      
         Request {

  
      
      
        private
      
      
         InputStream input;
  
      
      
        private
      
      
         String uri;

  
      
      
        public
      
      
         Request(InputStream input) {
    
      
      
        this
      
      .input =
      
         input;
  }

  
      
      
        public
      
      
        void
      
      
         parse() {
    
      
      
        //
      
      
         Read a set of characters from the socket
      
      
    StringBuffer request = 
      
        new
      
       StringBuffer(2048
      
        );
    
      
      
        int
      
      
         i;
    
      
      
        byte
      
      [] buffer = 
      
        new
      
      
        byte
      
      [2048
      
        ];
    
      
      
        try
      
      
         {
      i 
      
      =
      
         input.read(buffer);
    }
    
      
      
        catch
      
      
         (IOException e) {
      e.printStackTrace();
      i 
      
      = -1
      
        ;
    }
    
      
      
        for
      
       (
      
        int
      
       j=0; j<i; j++
      
        ) {
      request.append((
      
      
        char
      
      
        ) buffer[j]);
    }
    System.out.print(request.toString());
    uri 
      
      =
      
         parseUri(request.toString());
  }

  
      
      
        private
      
      
         String parseUri(String requestString) {
    
      
      
        int
      
      
         index1, index2;
    index1 
      
      = requestString.indexOf(' '
      
        );
    
      
      
        if
      
       (index1 != -1
      
        ) {
      index2 
      
      = requestString.indexOf(' ', index1 + 1
      
        );
      
      
      
        if
      
       (index2 >
      
         index1)
        
      
      
        return
      
       requestString.substring(index1 + 1
      
        , index2);
    }
    
      
      
        return
      
      
        null
      
      
        ;
  }

  
      
      
        public
      
      
         String getUri() {
    
      
      
        return
      
      
         uri;
  }

}
      
    

上面的void parse()方法是解析客戶端的請求參數,這里是解析客戶端請求的URL地址

Response類的代碼如下:

      
        /*
      
      
        
  HTTP Response = Status-Line
    *(( general-header | response-header | entity-header ) CRLF)
    CRLF
    [ message-body ]
    Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

      
      
        */
      
      
        public
      
      
        class
      
      
         Response {

  
      
      
        private
      
      
        static
      
      
        final
      
      
        int
      
       BUFFER_SIZE = 1024
      
        ;
  Request request;
  OutputStream output;

  
      
      
        public
      
      
         Response(OutputStream output) {
    
      
      
        this
      
      .output =
      
         output;
  }

  
      
      
        public
      
      
        void
      
      
         setRequest(Request request) {
    
      
      
        this
      
      .request =
      
         request;
  }

  
      
      
        public
      
      
        void
      
       sendStaticResource() 
      
        throws
      
      
         IOException {
    
      
      
        byte
      
      [] bytes = 
      
        new
      
      
        byte
      
      
        [BUFFER_SIZE];
    FileInputStream fis 
      
      = 
      
        null
      
      
        ;
    
      
      
        try
      
      
         {
      File file 
      
      = 
      
        new
      
      
         File(HttpServer.WEB_ROOT, request.getUri());
      
      
      
        if
      
      
         (file.exists()) {
        fis 
      
      = 
      
        new
      
      
         FileInputStream(file);
        
      
      
        int
      
       ch = fis.read(bytes, 0
      
        , BUFFER_SIZE);
        
      
      
        while
      
       (ch!=-1
      
        ) {
          output.write(bytes, 
      
      0
      
        , ch);
          ch 
      
      = fis.read(bytes, 0
      
        , BUFFER_SIZE);
        }
      }
      
      
      
        else
      
      
         {
        
      
      
        //
      
      
         file not found
      
      
        String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +
          "Content-Type: text/html\r\n" +
          "Content-Length: 23\r\n" +
          "\r\n" +
          "<h1>File Not Found</h1>"
      
        ;
        output.write(errorMessage.getBytes());
      }
    }
    
      
      
        catch
      
      
         (Exception e) {
      
      
      
        //
      
      
         thrown if cannot instantiate a File object
      
      
              System.out.println(e.toString() );
    }
    
      
      
        finally
      
      
         {
      
      
      
        if
      
       (fis!=
      
        null
      
      
        )
        fis.close();
    }
  }
}
      
    

這里最重要的是void sendStaticResource()方法,用于向輸出流寫入數據(這里是靜態文件),響應客戶端請求

本文介紹的是一個最簡單的web服務器,Tomcat容器的復雜性遠不止如此簡單,待后文接著分析

---------------------------------------------------------------------------?

本系列How Tomcat Works系本人原創?

轉載請注明出處 博客園 刺猬的溫馴?

本人郵箱: chenying998179 # 163.com ( #改為@

本文鏈接 http://www.cnblogs.com/chenying99/p/3229192.html

How Tomcat Works(二)


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 欧美福利在线视频 | 色片网 | 69视频在线观看福利视频 | 在线免费观看国产精品 | 狠狠激情五月综合婷婷俺 | 婷婷射| 成人亚洲天堂 | 亚洲在线免费观看 | 日本四虎影院 | 亚洲欧美中文字幕 | 精品欧美一区二区三区 | 夜夜夜夜夜夜夜猛噜噜噜噜噜噜 | 日韩一区二区三区视频 | 97人人视频 | 欧美亚洲国产精品久久久 | 99精品热 | 99国产福利视频区 | 四虎精品永久在线 | 国产精品亚洲欧美 | 在线91精品亚洲网站精品成人 | 色婷婷久久综合中文久久一本` | 奇米777四色影视在线看 | 一区二区三区免费精品视频 | 伊人丁香狠狠色综合久久 | 欧美一级毛片aaaaa | 我要看一级毛片 | 欧美亚洲h在线一区二区 | 国产农村1级毛片 | www.日日操 | xxxx成年视频免费 | 99热精品久久只有精品黑人 | ova熟肉动漫在线 | 中文字幕一级毛片视频 | 全部费免一级毛片不收费 | 日本h片a毛片在线播放 | 久久免费精品 | 久久精品福利 | 精品久久久久久蜜臂a∨ | 日韩欧美视频在线播放 | 夜夜骑日日操 | 亚洲免费视频播放 |