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

試解析Tomcat運行原理(一)--- socket通訊

系統 2503 0

  關于這篇文章也確實籌劃了很久,今天決定開篇寫第一篇,說起 tomcat 首先很容易聯想到 IIS ,因為我最開始使用的就是 .net 技術,我第一次使用 asp 寫學生成績管理系統后,很茫然如何讓別人都能看到或者說使用這個系統呢?由此認識了 IIS ,它是一個 web 容器,天生的多線程,及時響應用戶提交的請求返回 html 頁面,這就是我了解的最初的 web 容器的功能,由此我們來認識 tomcat 也并不困難,可以的話,在了解完 tomcat 后我們可以繼續了解 jboss jetty 等,好我們進入主題。

  我們在平時開發的過程中是在使用 eclipse 時候才啟動 tomcat ,對于一個 web 容器而言,簡而言之,它是系統的一個守護進程,守護著對這臺服務器某個端口發起的請求,基于這一點,它就需要一個監聽程序,這個監聽程序來獲取來自這個端口的特定請求的數據, ok ,直接點講,我們這里使用 Socket 來獲取某個端口,通常是 80 端口的 http 請求,通過簡單的 Java

  程序的死循環(粗糙的做法,后面逐步優化)來實現不斷的獲取 80 端口 http 請求,來達到監聽 80 端口 http 請求的目的。j ava.net包 下面的 Socket ServerSocket 兩個類就能實現我們對 8080 端口的監聽,去除中間的邏輯代碼,我們只看這個兩個類的演繹的話如下:

?

      
        1
      
       ServerSocket serverSocket = 
      
        new
      
       ServerSocket(8080, 1, InetAddress.getByName("10.10.10.106"));
    

?

  對本機的 8080 端口進行監聽

?

      
        1
      
       socket =
      
         serverSocket.accept();             


      
      
        2
      
       input =
      
         socket.getInputStream(); 


      
      
        3
      
       output = socket.getOutputStream(); 
    

?

  以上代碼就是獲取監聽結果。

  這是最簡單和最精簡的Socket 通訊原理,基于這個核心點我們來開發一個簡易的,可以提供靜態頁面訪問的? custom?tomcat ,準備一個 index.html 文件放到 /home/webroot 目錄下,那么除去拓展上面代碼外,我們還需要一個 Response 和一個 Request

  類設計如下:

  HttpServer :?主函數所在類,負載啟動 ServerSocket 和?操作整合 Socket 監聽到的數據,以及返回結果,即操作 Response Request

  Request:? 封裝 Socket 監聽到的用戶端請求,包括請求的 http?uri 信息。

  Response :?封裝需要推送到客戶端的結果數據,即我們需要根據 http?uri? 去本機尋找相應的資源,寫給客戶端。

  言簡意賅,進入代碼,首先? Request 類代碼:

?

      
         1
      
      
        public
      
      
        class
      
      
         Request 


      
      
         2
      
      
        {


      
      
         3
      
      
        private
      
      
         InputStream input;


      
      
         4
      
      
        private
      
      
         String uri;


      
      
         5
      
      
         6
      
      
        public
      
      
         Request(InputStream input) {


      
      
         7
      
      
        this
      
      .input =
      
         input;


      
      
         8
      
      
            }


      
      
         9
      
      
        10
      
      
        public
      
      
        void
      
      
         parse()


      
      
        11
      
      
            {


      
      
        12
      
               StringBuffer request = 
      
        new
      
       StringBuffer(2048
      
        );


      
      
        13
      
      
        int
      
      
         i;


      
      
        14
      
      
        byte
      
      [] buffer = 
      
        new
      
      
        byte
      
      [2048
      
        ];


      
      
        15
      
      
        try
      
      
        16
      
      
                { 


      
      
        17
      
                    i =
      
         input.read(buffer);


      
      
        18
      
      
                }


      
      
        19
      
      
        catch
      
      
        (IOException e) 


      
      
        20
      
      
                { 


      
      
        21
      
      
                     e.printStackTrace(); 


      
      
        22
      
                    i = -1
      
        ; 


      
      
        23
      
      
                }


      
      
        24
      
      
        25
      
      
        for
      
       (
      
        int
      
       j=0; j<i; j++
      
        ) 


      
      
        26
      
      
                {


      
      
        27
      
                   request.append((
      
        char
      
      
        ) buffer[j]);


      
      
        28
      
      
                } 


      
      
        29
      
      
                System.out.print(request.toString()); 


      
      
        30
      
               uri =
      
         parseUri(request.toString());


      
      
        31
      
      
            }


      
      
        32
      
      
        33
      
      
        private
      
      
         String parseUri(String requestString) 


      
      
        34
      
      
            {  


      
      
        35
      
      
        int
      
      
         index1, index2; 


      
      
        36
      
               index1 = requestString.indexOf(' '
      
        );


      
      
        37
      
      
        if
      
       (index1 != -1
      
        ) { 


      
      
        38
      
                   index2 = requestString.indexOf(' ', index1 + 1
      
        );


      
      
        39
      
      
        if
      
       (index2 >
      
         index1) 


      
      
        40
      
      
        return
      
       requestString.substring(index1 + 1
      
        , index2); 


      
      
        41
      
      
                    }  


      
      
        42
      
      
        return
      
      
        null
      
      
        ;


      
      
        43
      
      
            }


      
      
        44
      
      
        45
      
      
        public
      
      
         String getUri() 


      
      
        46
      
      
            {


      
      
        47
      
      
        return
      
      
         uri;


      
      
        48
      
      
            }


      
      
        49
      
       }
    

?

  代碼解釋:類包括一個屬性和兩個方法, input 屬性即是從 Socket 監聽到的信息, Socket 會將監聽到的信息放入一個 InputStream 中,我們使用 Reqeust 類的 Input 屬性來接受。接收到輸入流后,在 parse 中對這個輸入流進行解析成字符串,即對 Http 請求進行拆解,得到完整的 Http?URL ,所以這個方法是私有的,是類存在意義的核心所在,而提供的對外方法 parseUri 是負載將 parse 解析的 url 結果提供給外界,即,客戶端發來請求那個文件,具體的是最終提供給 Response 類, Response 類得到這個文件名稱后,去本地制定目錄讀取文件。 Tomcat 中通常就是 webapps 目錄啦,很熟悉了吧,哈哈。

  Response 類如何實現這個讀取文件的歷史使命呢,代碼如下 :

?

      
         1
      
      
        public
      
      
        class
      
      
         Response {


      
      
         2
      
      
         3
      
      
        private
      
      
        static
      
      
        final
      
      
        int
      
       BUFFER_SIZE = 1024
      
        ; 


      
      
         4
      
      
            Request request; 


      
      
         5
      
      
            OutputStream output;


      
      
         6
      
      
         7
      
      
        public
      
      
         Response(OutputStream output) 


      
      
         8
      
      
            { 


      
      
         9
      
      
        this
      
      .output =
      
         output;


      
      
        10
      
      
            }


      
      
        11
      
      
        12
      
      
        public
      
      
        void
      
      
         setRequest(Request request)


      
      
        13
      
      
            {


      
      
        14
      
      
        this
      
      .request =
      
         request;


      
      
        15
      
      
            }


      
      
        16
      
      
        17
      
      
        public
      
      
        void
      
       sendStaticResource() 
      
        throws
      
      
         IOException


      
      
        18
      
      
            {


      
      
        19
      
      
        byte
      
      [] bytes = 
      
        new
      
      
        byte
      
      
        [BUFFER_SIZE];


      
      
        20
      
               FileInputStream fis = 
      
        null
      
      
        ;


      
      
        21
      
      
        try
      
      
        22
      
      
                {


      
      
        23
      
                       File file = 
      
        new
      
      
         File(HttpServer.WEB_ROOT, request.getUri());


      
      
        24
      
      
        if
      
      
         (file.exists())


      
      
        25
      
      
                        { 


      
      
        26
      
                               fis = 
      
        new
      
      
         FileInputStream(file); 


      
      
        27
      
      
        int
      
       ch = fis.read(bytes, 0
      
        , BUFFER_SIZE); 


      
      
        28
      
      
        while
      
       (ch!=-1
      
        ) { 


      
      
        29
      
                                   output.write(bytes, 0
      
        , ch); 


      
      
        30
      
                                   ch = fis.read(bytes, 0
      
        , BUFFER_SIZE);


      
      
        31
      
      
                                }


      
      
        32
      
      
                        }


      
      
        33
      
      
        else
      
      
        34
      
      
                        {


      
      
        35
      
                           String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +


      
        36
      
                               "Content-Type: text/html\r\n" + 


      
        37
      
                               "Content-Length: 23\r\n" +


      
        38
      
                               "\r\n" +


      
        39
      
                               "<h1>File Not Found</h1>"
      
        ;


      
      
        40
      
      
                            output.write(errorMessage.getBytes());


      
      
        41
      
      
                        }


      
      
        42
      
      
                }


      
      
        43
      
      
        catch
      
      
        (Exception e) 


      
      
        44
      
      
                {


      
      
        45
      
      
                        System.out.println(e.toString());


      
      
        46
      
      
                }


      
      
        47
      
      
        finally
      
      
        {


      
      
        48
      
      
                    fis.close();


      
      
        49
      
      
                }


      
      
        50
      
      
        51
      
      
            }


      
      
        52
      
       }
    

?

  代碼解釋: Response 一共三個屬性,一個方法。三個屬性,一個是設置屬性, BUFFER_SIZE 設置讀寫字節流大小,關于讀寫文件,我個人覺得和服務器的性能和程序性能息息相關,不宜設定過大或過小(此處有不同見解的同仁歡迎來噴,我對這塊理解目前限于此)。 Reqeust 屬性,對照前文呼應, Response 需要獲取 Request 類的 uri 結果信息,所以這里放了一個 Request 屬性,獲取 uri Output ,就不用說了,也是這個類存在的核心意義,依照 Request 類提供的 uri 信息,在本地讀寫文件后,形成一個輸出來,存放到 output 中,那么這項工作就由 sendStaticResource 這個共有方法完成啦。

  好,代碼到這個,可以說我們大家已經看到一個 tomcat 模型了,有點萬事俱備,只欠東風的感覺,客戶端發起請求, Response Reqeust 有了,那么繼續往上游考慮, Reqeust 依賴于客戶端的請求,自然以來于 Socket 數據。我們在這里做得簡便一點,將 ServerSocket Socket 封裝到一個 HttpServer 類中來,代碼如下:

?

      
         1
      
      
        public
      
      
        class
      
      
         HttpServer {


      
      
         2
      
      
         3
      
      
        public
      
      
        static
      
      
        final
      
       String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot"
      
        ;


      
      
         4
      
      
        private
      
      
        static
      
      
        final
      
       String SHUTDOWN_COMMAND = "/SHUTDOWN"
      
        ;


      
      
         5
      
      
        private
      
      
        boolean
      
       shutdown = 
      
        false
      
      
        ;


      
      
         6
      
      
        public
      
      
        static
      
      
        void
      
      
         main(String[] args)


      
      
         7
      
      
            {


      
      
         8
      
               HttpServer httpServer = 
      
        new
      
      
         HttpServer();


      
      
         9
      
      
                httpServer.await();


      
      
        10
      
      
            }


      
      
        11
      
      
        12
      
      
        public
      
      
        void
      
      
         await()


      
      
        13
      
      
            {


      
      
        14
      
               ServerSocket serverSocket = 
      
        null
      
      
        ;


      
      
        15
      
               Integer port = 8080
      
        ; 


      
      
        16
      
      
        try
      
      
        17
      
      
                { 


      
      
        18
      
                   serverSocket =  
      
        new
      
       ServerSocket(port, 1, InetAddress.getByName("10.10.10.106"
      
        )); 


      
      
        19
      
      
                } 


      
      
        20
      
      
        catch
      
      
        (IOException e)     


      
      
        21
      
      
                { 


      
      
        22
      
      
                    e.printStackTrace(); 


      
      
        23
      
                   System.exit(1
      
        ); 


      
      
        24
      
      
                } 


      
      
        25
      
      
        26
      
      
        while
      
      (!
      
        shutdown)


      
      
        27
      
      
                {


      
      
        28
      
                   Socket socket = 
      
        null
      
      
        ;


      
      
        29
      
                   InputStream input = 
      
        null
      
      
        ;


      
      
        30
      
                   OutputStream output = 
      
        null
      
      
        ;


      
      
        31
      
      
        try
      
      
        32
      
      
                    { 


      
      
        33
      
                       socket =
      
         serverSocket.accept();


      
      
        34
      
      
        35
      
                       input =
      
         socket.getInputStream(); 


      
      
        36
      
                       output =
      
         socket.getOutputStream(); 


      
      
        37
      
                       Request request = 
      
        new
      
      
         Request(input); 


      
      
        38
      
      
                        request.parse(); 


      
      
        39
      
                       Response response = 
      
        new
      
      
         Response(output);


      
      
        40
      
      
                        response.setRequest(request); response.sendStaticResource();  socket.close(); 


      
      
        41
      
                       shutdown =
      
         request.getUri().equals(SHUTDOWN_COMMAND);


      
      
        42
      
      
                    }


      
      
        43
      
      
        catch
      
      
        (Exception e) 


      
      
        44
      
      
                    {


      
      
        45
      
                       e.printStackTrace();
      
        continue
      
      
        ;


      
      
        46
      
      
                    }


      
      
        47
      
      
                }


      
      
        48
      
      
            }


      
      
        49
      
       }
    

?

  代碼解釋:我們知道啟動 tomcat 之后,只要服務正常,客戶端任意時候發起一個 http 請求, tomcat 就會響應,那么這里我們肯定需要一個 while 循環來模擬不間斷的監聽,類 await 方法就是負責不斷的獲取 socket 監聽到的結果,有立刻調動 Reqeust Response 進行響應,加入主函數,為的是我們這個是模擬的控制臺程序,需要一個程序入口, main 函數就是程序入口。此外, HttpServer 類包括一個靜態屬性 SHUTDOWN_COMMAND ,輸入為 true 則停止這個 main 函數,變量初始值為 false ,當客戶端也就是 Request 響應得到客戶端輸入? http://10.10.10.108:8080/SHUTDOWN 時候,則變量在 while 中會置成 true ,緊接著停止 main ,結束應用程序進程。

  在 eclipse 中或者在命令行中啟動這個 main 函數,命令行則是輸入? java?HttpServer.java eclipse 則是在 main 函數中右鍵? run?as?application 啟動。 我們打開瀏覽器,輸入? http://10.10.10.108:8080/index.html, 回車結果如下:

試解析Tomcat運行原理(一)--- socket通訊

  本地文件:

  好了,夜深啦,就此擱筆了,拋磚引玉,歡迎提議和討論,這個系列會繼續下去,直到一個完整的可以響應一個java action請求的custom tomcat產品出來。

  最后附上我的源代碼:http://files.cnblogs.com/aspnetdream/Project.zip

  參考:《How tomcat works》?作者:Budi Kurniawan & Paul Deck

?

試解析Tomcat運行原理(一)--- socket通訊


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

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

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

【本文對您有幫助就好】

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

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 亚洲精品一区二区三区福利 | 亚洲免费资源 | 26uuu最新 | 午夜三级做爰视频在线看 | 亚洲码在线中文在线观看 | 成年女人视频免费观看一 | 国产精品入口麻豆 | 亚洲免费在线视频播放 | 九九热热 | www.国产在线观看 | 欧美久久久久久久久 | 成人ab片 | 97精品福利视频在线 | 亚洲久久色 | 大ji吧快给我别停受不了视频 | 亚洲乱码视频 | 欧美日韩一区二区高清免费视频 | 青青青爽视频在线观看 | 日韩va | 亚洲国产系列久久精品99人人 | 五月花精品视频在线观看 | 亚洲图片一区二区 | 亚洲精品无码不卡在线播放he | 男女啪啪网站 | 又粗又大的机巴好爽7 | 亚洲小视频在线播放 | 亚洲国产成a人v在线观看 | 国产亚洲精品色一区 | 鲁一鲁中文字幕久久 | 天天干天天操天天插 | 亚洲精品mm1313久久 | 日韩av片免费播放 | 伊人狠狠丁香婷婷综合色 | 欧美日韩91 | 亚洲国产最新在线一区二区 | 五月综合激情视频在线观看 | 国产一区在线看 | 99热在线看| 奇米影视狠狠狠天天777 | 午夜欧美| 国产精品柳州莫菁身材四 |