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

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

系統(tǒng) 2170 0

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

  我們?cè)谄綍r(shí)開發(fā)的過程中是在使用 eclipse 時(shí)候才啟動(dòng) tomcat ,對(duì)于一個(gè) web 容器而言,簡(jiǎn)而言之,它是系統(tǒng)的一個(gè)守護(hù)進(jìn)程,守護(hù)著對(duì)這臺(tái)服務(wù)器某個(gè)端口發(fā)起的請(qǐng)求,基于這一點(diǎn),它就需要一個(gè)監(jiān)聽程序,這個(gè)監(jiān)聽程序來獲取來自這個(gè)端口的特定請(qǐng)求的數(shù)據(jù), ok ,直接點(diǎn)講,我們這里使用 Socket 來獲取某個(gè)端口,通常是 80 端口的 http 請(qǐng)求,通過簡(jiǎn)單的 Java

  程序的死循環(huán)(粗糙的做法,后面逐步優(yōu)化)來實(shí)現(xiàn)不斷的獲取 80 端口 http 請(qǐng)求,來達(dá)到監(jiān)聽 80 端口 http 請(qǐng)求的目的。j ava.net包 下面的 Socket ServerSocket 兩個(gè)類就能實(shí)現(xiàn)我們對(duì) 8080 端口的監(jiān)聽,去除中間的邏輯代碼,我們只看這個(gè)兩個(gè)類的演繹的話如下:

?

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

?

  對(duì)本機(jī)的 8080 端口進(jìn)行監(jiān)聽

?

      
        1
      
       socket =
      
         serverSocket.accept();             


      
      
        2
      
       input =
      
         socket.getInputStream(); 


      
      
        3
      
       output = socket.getOutputStream(); 
    

?

  以上代碼就是獲取監(jiān)聽結(jié)果。

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

  類設(shè)計(jì)如下:

  HttpServer :?主函數(shù)所在類,負(fù)載啟動(dòng) ServerSocket 和?操作整合 Socket 監(jiān)聽到的數(shù)據(jù),以及返回結(jié)果,即操作 Response Request

  Request:? 封裝 Socket 監(jiān)聽到的用戶端請(qǐng)求,包括請(qǐng)求的 http?uri 信息。

  Response :?封裝需要推送到客戶端的結(jié)果數(shù)據(jù),即我們需要根據(jù) http?uri? 去本機(jī)尋找相應(yīng)的資源,寫給客戶端。

  言簡(jiǎn)意賅,進(jìn)入代碼,首先? 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
      
       }
    

?

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

  Response 類如何實(shí)現(xiàn)這個(gè)讀取文件的歷史使命呢,代碼如下 :

?

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

  好,代碼到這個(gè),可以說我們大家已經(jīng)看到一個(gè) tomcat 模型了,有點(diǎn)萬事俱備,只欠東風(fēng)的感覺,客戶端發(fā)起請(qǐng)求, Response Reqeust 有了,那么繼續(xù)往上游考慮, Reqeust 依賴于客戶端的請(qǐng)求,自然以來于 Socket 數(shù)據(jù)。我們?cè)谶@里做得簡(jiǎn)便一點(diǎn),將 ServerSocket Socket 封裝到一個(gè) 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
      
       }
    

?

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

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

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

  本地文件:

  好了,夜深啦,就此擱筆了,拋磚引玉,歡迎提議和討論,這個(gè)系列會(huì)繼續(xù)下去,直到一個(gè)完整的可以響應(yīng)一個(gè)java action請(qǐng)求的custom tomcat產(chǎn)品出來。

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

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

?

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


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

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

【本文對(duì)您有幫助就好】

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

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 中文字幕亚洲一区二区三区 | 夜夜狠狠| 真人女人一级毛片免费视频观看 | 亚洲婷婷综合色高清在线 | 欧美日韩视频在线 | 久久精品美女视频 | 五月婷婷激情在线 | 久久www免费人成_看 | 国产精品香蕉在线观看不卡 | 久久国产欧美日韩精品免费 | 欧美成人在线观看 | 毛片b| 91在线视频免费播放 | 国内精品欧美久久精品 | 成人欧美一区在线视频在线观看 | 黄色网欧美 | 一本色道久久综合亚洲精品 | 日本国产一区二区三区 | 午夜精品久久影院蜜桃 | 久久精品视频大全 | 操穴影院 | 国产精品欧美亚洲韩国日本99 | 国产一级精品毛片 | 九色av99久久| 四虎精品久久 | 国产免费成人在线视频 | 国产综合婷婷 | 欧美日韩一级大片 | 久久精品国产半推半就 | 四虎影视免费 | 久久久久久全国免费观看 | 国产精品1区2区3区在线播放 | 日韩精品免费一级视频 | 欧美毛片免费 | 91成人免费在线视频 | 久久精品免视看国产成人2021 | 久久精品国产亚洲高清 | 日本一级α一片免费视频 | 看一级特黄a大片日本片黑人 | 久久99精品久久久久久h | 97在线视频免费播放 |