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

Tomcat是怎么工作的(2) -- 動(dòng)手實(shí)現(xiàn)山寨版的簡(jiǎn)

系統(tǒng) 2275 0

????? 本文先講解一下Java web server都是怎么工作的。web server也叫HTTP server——顧名思義它是用HTTP協(xié)議和客戶端交互的??蛻舳艘话憔褪歉鞣N各樣的瀏覽器了。相信所有朋友都清楚這個(gè)基本事實(shí),否則你也不會(huì)看到這個(gè)系列文章了。

????? 基于Java的web server必然用到兩個(gè)極其重要的類:java.net.Socket和java.net.ServerSocket,然后以HTTP消息進(jìn)行交互。

1. HTTP協(xié)議簡(jiǎn)介(The Hypertext Transfer Protocol)

????? HTTP是用于web server和瀏覽器之間發(fā)送、接收數(shù)據(jù)的基礎(chǔ)核心協(xié)議——客戶端發(fā)起請(qǐng)求然后服務(wù)端進(jìn)行響應(yīng)。它使用應(yīng)答式TCP連接,默認(rèn)情況下監(jiān)聽(tīng)在80端口上。第一版協(xié)議是HTTP/0.9,然后又被HTTP/1.0重寫了,隨后HTTP/1.1又替換掉了HTTP/1.0——當(dāng)前我們使用的正是HTTP/1.1,它的協(xié)議文件叫RFC2616,有興趣的可以去w3網(wǎng)站上下載回來(lái)研究一下,對(duì)你理解和掌握HTTP以及整個(gè)互聯(lián)網(wǎng)的核心有著無(wú)可替代的作用。接地氣的說(shuō)法就是:明白了RFC2616,你就明白了易筋經(jīng)和九陽(yáng)神功,自此之后橫行天下無(wú)所顧忌。。。

????? HTTP里,永遠(yuǎn)都是客戶端主動(dòng)發(fā)起請(qǐng)求,然后服務(wù)端才有可能和它建立連接。web server永遠(yuǎn)不會(huì)主動(dòng)連接或者回調(diào)客戶端,但是兩邊都可以直接斷開(kāi)連接。

????? 總結(jié)成一句話就是:服務(wù)端永遠(yuǎn)處于絕對(duì)優(yōu)勢(shì)地位,客戶端你不連我我就絕對(duì)不會(huì)連你,只有你客戶端發(fā)起請(qǐng)求了,我服務(wù)端才會(huì)和你連接,當(dāng)然,心情不好時(shí)我也照樣可以不對(duì)你的請(qǐng)求做出任何響應(yīng)。像極了男人追女人的戀愛(ài)過(guò)程吧。。。

1.1 HTTP請(qǐng)求

????? 它由以下部分組成:

????? 第一部分:方式 — URI — 協(xié)議/版本號(hào)

????? 第二部分:請(qǐng)求頭

????? 第三部分:實(shí)體數(shù)據(jù)

????? 典型例如如下:

      
           1:  
      
      POST /baidu.com/小蘋果歌詞.txt HTTP/1.1
    
      
           2:  
      
      ?
    
      
           3:  
      
      Accept: text/plain; text/html 
    
      
           4:  
      
      Accept-Language: en-gb 
    
      
           5:  
      
      Connection: Keep-Alive 
    
      
           6:  
      
      Host: localhost 
    
      
           7:  
      
      User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 98) 
    
      
           8:  
      
      Content-Length: 33 
    
      
           9:  
      
      Content-Type: application/x-www-form-urlencoded 
    
      
          10:  
      
      Accept-Encoding: gzip, deflate 
    
      
          11:  
      
      ?
    
      
          12:  
      
      lastName=Franks&firstName=Michael
    

?

???? 對(duì)應(yīng)的第一部分就是這段請(qǐng)求信息的第一行,下面再詳細(xì)講解下:

???? POST /baidu.com/小蘋果歌詞.txt HTTP/1.1

???? 這一行的“POST”是請(qǐng)求方式,“/baidu.com/小蘋果歌詞.txt”是對(duì)應(yīng)的URI,而“HTTP/1.1”就是對(duì)應(yīng)的協(xié)議/版本號(hào)了。

???? HTTP協(xié)議定義了很多請(qǐng)求方式,每一個(gè)HTTP請(qǐng)求都可以使用其中的一種。HTTP 1.1 支持7種請(qǐng)求類型:GET,POST,HEAD,OPTIONS,PUT,DELETE以及TRACE。一般情況下,我們只用到GET和POST就足夠了。

???? URI完整的指定了一個(gè)網(wǎng)絡(luò)資源,一般情況下它都是相對(duì)于服務(wù)器的根目錄進(jìn)行資源定位,你看到的URI才經(jīng)常以斜杠“/”開(kāi)頭,當(dāng)然,通常我們只知道URL,URL實(shí)際上只是URI的一種而已(細(xì)節(jié)可研究RFC2396協(xié)議)。第一行的協(xié)議版本號(hào),顧名思義就是當(dāng)前使用的是哪版HTTP協(xié)議了。

???? 請(qǐng)求頭包含了一些關(guān)于客戶端環(huán)境和請(qǐng)求體的有用信息。例如,它可以指示瀏覽器使用的語(yǔ)言、請(qǐng)求體的數(shù)據(jù)長(zhǎng)度等等。每一個(gè)請(qǐng)求頭和請(qǐng)求體之間都通過(guò)回車換行符(CRLF)分隔。

???? 請(qǐng)求頭和請(qǐng)求體之間的空白行(CRLF)是HTTP請(qǐng)求格式中不可或缺的一部分,它用于指明請(qǐng)求體數(shù)據(jù)開(kāi)始的w位置。甚至在一些網(wǎng)絡(luò)編程書中,這個(gè)空白行(CRLF)直接被當(dāng)作了HTTP請(qǐng)求標(biāo)準(zhǔn)格式的第四個(gè)組成部分。

???? 在上面那個(gè)例子中,請(qǐng)求體的實(shí)體數(shù)據(jù)只有簡(jiǎn)單的一行,不過(guò)實(shí)際應(yīng)用中實(shí)體數(shù)據(jù)往往比較多:

???? lastName=Franks&firstName=Michael

???? 1.2 HTTP響應(yīng)

???? 和HTTP請(qǐng)求相似,HTTP響應(yīng)也由三部分組成:

???? 第一部分:協(xié)議 -- 狀態(tài)碼 --描述

???? 第二部分:響應(yīng)頭

???? 第三部分:響應(yīng)體

???? 舉個(gè)例子:

      
           1:  
      
      HTTP/1.1 200 OK 
    
      
           2:  
      
      Server: Microsoft-IIS/4.0 
    
      
           3:  
      
      Date: Mon, 5 Jan 2004 13:13:33 GMT 
    
      
           4:  
      
      Content-Type: text/html 
    
      
           5:  
      
      Last-Modified: Mon, 5 Jan 2004 13:13:12 GMT 
    
      
           6:  
      
      Content-Length: 112 
    
      
           7:  
      
      ?
    
      
           8:  
      
      
        <
      
      
        html
      
      
        >
      
    
      
           9:  
      
      
        <
      
      
        head
      
      
        >
      
    
      
          10:  
      
      
        <
      
      
        title
      
      
        >
      
      HTTP Response Example
      
        </
      
      
        title
      
      
        >
      
    
      
          11:  
      
      
        </
      
      
        head
      
      
        >
      
    
      
          12:  
      
      
        <
      
      
        body
      
      
        >
      
    
      
          13:  
      
           Welcome to Brainy Software 
    
      
          14:  
      
      
        </
      
      
        body
      
      
        >
      
    
      
          15:  
      
      
        </
      
      
        html
      
      
        >
      
    
      ?
    

???? 響應(yīng)頭第一行和請(qǐng)求頭極為相似,它指示了當(dāng)前使用的協(xié)議是HTTP/1.1版本,而且請(qǐng)求成功了(200=成功),一切順利。
響應(yīng)頭包含的有用信息類似于請(qǐng)求頭的。響應(yīng)體是一段HTML內(nèi)容,響應(yīng)頭和響應(yīng)體之間以CRLF分隔。


2. Socket類
????? socket是網(wǎng)絡(luò)連接的一個(gè)端點(diǎn),它賦予應(yīng)用程序讀寫網(wǎng)絡(luò)流的能力。兩臺(tái)電腦通過(guò)發(fā)送和接收基于連接的字節(jié)流來(lái)進(jìn)行交流溝通。若要發(fā)消息給另一個(gè)程序,你需要知道這個(gè)程序socket的ip地址和端口號(hào)。在java里,socket指的是java.net.Socket類。


????? 你可以使用Socket類的諸多構(gòu)造器中任意一個(gè)來(lái)創(chuàng)建socket,下面這個(gè)構(gòu)造器接收主機(jī)名和端口號(hào)作為參數(shù):
????? public Socket (java.lang.String host, int port)


????? 在此,host可以是主機(jī)名或者ip地址,端口號(hào)就是對(duì)應(yīng)的程序占用的端口。例如,要想連接80端口上的yahoo.com,你需要如下構(gòu)造方式:
????? new Socket("yahoo.com", 80);


????? 一旦成功創(chuàng)建Socket實(shí)例,你就可以用它來(lái)發(fā)送接收字節(jié)流了。要發(fā)送字節(jié)流,你必須首先調(diào)用Socket類的getOutputStream方法獲取java.io.OutputStream對(duì)象,要發(fā)送純文本的話,我們通常構(gòu)造一個(gè)OutputStream對(duì)象返回的java.io.PrintWriter對(duì)象。要接收字節(jié)流,你就應(yīng)該調(diào)用Socket類的getInputStream方法來(lái)獲取 java.io.InputStream。


下面就是代碼展示了,各位看官請(qǐng)好:

      
           1:  
      
      Socket socket = 
      
        new
      
       Socket(
      
        "127.0.0.1"
      
      , 
      
        "8080"
      
      ); 
    
      
           2:  
      
      OutputStream os = socket.getOutputStream(); 
    
      
           3:  
      
      boolean autoflush = 
      
        true
      
      ; 
    
      
           4:  
      
      PrintWriter 
      
        out
      
       = 
      
        new
      
       PrintWriter( socket.getOutputStream(), autoflush); 
    
      
           5:  
      
      BufferedReader 
      
        in
      
       = 
      
        new
      
       BufferedReader( 
      
        new
      
       InputStreamReader( socket.getInputstream() )); 
    
      
           6:  
      
      ?
    
      
           7:  
      
      
        // 向web server發(fā)送HTTP請(qǐng)求
      
    
      
           8:  
      
      
        out
      
      .println(
      
        "GET /index.jsp HTTP/1.1"
      
      ); 
    
      
           9:  
      
      
        out
      
      .println(
      
        "Host: localhost:8080"
      
      );
    
      
          10:  
      
      
        out
      
      .println(
      
        "Connection: Close"
      
      ); 
    
      
          11:  
      
      
        out
      
      .println(); 
    
      
          12:  
      
      ?
    
      
          13:  
      
      
        // 讀取響應(yīng)
      
    
      
          14:  
      
      boolean loop = 
      
        true
      
      ; 
    
      
          15:  
      
      StringBuffer sb = 
      
        new
      
       StringBuffer(8096); 
    
      
          16:  
      
      
        while
      
       (loop) { 
    
      
          17:  
      
      
        if
      
       ( 
      
        in
      
      .ready() ) { 
    
      
          18:  
      
      
        int
      
       i=0;
    
      
          19:  
      
      
        while
      
       (i!=-1) { 
    
      
          20:  
      
                  i = 
      
        in
      
      .read(); 
    
      
          21:  
      
                  sb.append((
      
        char
      
      ) i); 
    
      
          22:  
      
              } 
    
      
          23:  
      
              loop = 
      
        false
      
      ; 
    
      
          24:  
      
          } 
    
      
          25:  
      
          Thread.currentThread().sleep(50); 
    
      
          26:  
      
      } 
    
      
          27:  
      
      ?
    
      
          28:  
      
      
        // 輸出響應(yīng)內(nèi)容 
      
    
      
          29:  
      
      System.
      
        out
      
      .println(sb.toString()); 
    
      
          30:  
      
      socket.close();
    

?

3. ServerSocket類
????? Socket類代表的是客戶端Socket,例如IE瀏覽器、chrome、火狐、safari等發(fā)起的連接。如果你想實(shí)現(xiàn)一個(gè)服務(wù)器應(yīng)用程序,像HTTP server或者FTP server的話,你就必須使用不同的方法了。這是因?yàn)榉?wù)端根本不知道客戶端會(huì)發(fā)起請(qǐng)求建立連接,它必須永不停歇的等待客戶端請(qǐng)求。為此,你必須使用java.net.ServerSocket類,它是服務(wù)端socket的實(shí)現(xiàn)。


????? ServerSocket不同于Socket,服務(wù)端的ServerSocket必須一直等著客戶端請(qǐng)求的到來(lái)。一旦server socket接到連接請(qǐng)求,它必須創(chuàng)建一個(gè)Socket實(shí)例來(lái)處理和客戶端的交互。


????? 要?jiǎng)?chuàng)建server socket,你得用ServerSocket類提供的四個(gè)構(gòu)造器之一。它需要你指明IP地址和server socket要監(jiān)聽(tīng)的端口號(hào)。經(jīng)典的127.0.0.1意味著server socket將監(jiān)聽(tīng)本機(jī)。server socket監(jiān)聽(tīng)的IP地址通常也叫綁定地址。另一個(gè)重要的屬性是backlog,它意味著接入的連接請(qǐng)求超過(guò)此數(shù)值之后server socket就會(huì)拒絕后續(xù)請(qǐng)求。


????? public ServerSocket(int port, int backlog, InetAddress bindingAddress);


????? 值得注意的是,這個(gè)構(gòu)造器的綁定地址必須是java.net.InetAddress類的實(shí)例。構(gòu)造InetAddress對(duì)象的簡(jiǎn)易方法就是調(diào)用它的靜態(tài)方法getByname,并傳一個(gè)主機(jī)名字符創(chuàng)參數(shù),如下所示:
????? InetAddress.getByName("127.0.0.1");


????? 下面這行代碼構(gòu)造了一個(gè)ServerSocket,監(jiān)聽(tīng)本機(jī)8080端口,同時(shí)backlog為1:
????? new ServerSocket(8080, 1, InetAddress.getByName("127.0.0.1"));


????? 一旦ServerSocket實(shí)例構(gòu)造完成,它就可以一直監(jiān)聽(tīng)在綁定地址的對(duì)應(yīng)端口上等待請(qǐng)求的到來(lái),你需要做的就是調(diào)用ServerSocket類的accept方法來(lái)啟動(dòng)這個(gè)監(jiān)聽(tīng)過(guò)程。這個(gè)方法只返回何時(shí)產(chǎn)生了連接請(qǐng)求并且返回值是一個(gè)Sokcet類的實(shí)例。然后通過(guò)這個(gè)Socket可以發(fā)送和接收字節(jié)流。


4. 動(dòng)手實(shí)現(xiàn)自己的山寨版web server
????? 這個(gè)山寨web server由三個(gè)類組成:HttpServer、Request、Response。
????? HttpServer的main方法創(chuàng)建一個(gè)HttpServer實(shí)例并調(diào)用它的await方法,顧名思義,這個(gè)await方法一直等著請(qǐng)求到來(lái),然后處理請(qǐng)求、發(fā)送響應(yīng)信息到客戶端。它會(huì)一直等,直到程序終止或停機(jī)。
????? 這個(gè)山寨版的server目前只能發(fā)送靜態(tài)資源,它會(huì)在控制臺(tái)顯示HTTP請(qǐng)求的字節(jié)流,但不能發(fā)送任何響應(yīng)頭,比如data、cookie之類的。


4.1 HTTPServer.java

?

      
           1:  
      
      import java.io.File;
    
      
           2:  
      
      import java.io.IOException;
    
      
           3:  
      
      import java.io.InputStream;
    
      
           4:  
      
      import java.io.OutputStream;
    
      
           5:  
      
      import java.net.InetAddress;
    
      
           6:  
      
      import java.net.ServerSocket;
    
      
           7:  
      
      import java.net.Socket;
    
      
           8:  
      
      ?
    
      
           9:  
      
      
        public
      
      
        class
      
       HttpServer {
    
      
          10:  
      
      ?
    
      
          11:  
      
      
        /**
      
    
      
          12:  
      
      
             * WEB_ROOT is the directory where our HTML and other files reside. For this
      
    
      
          13:  
      
      
             * package, WEB_ROOT is the "webroot" directory under the working directory.
      
    
      
          14:  
      
      
             * The working directory is the location in the file system from where the
      
    
      
          15:  
      
      
             * java command was invoked.
      
    
      
          16:  
      
      
             */
      
    
      
          17:  
      
      
        public
      
      
        static
      
       final String WEB_ROOT = System.getProperty(
      
        "user.dir"
      
      ) + File.separator + 
      
        "webroot"
      
      ;
    
      
          18:  
      
      ?
    
      
          19:  
      
      
        // 關(guān)機(jī)命令
      
    
      
          20:  
      
      
        private
      
      
        static
      
       final String SHUTDOWN_COMMAND = 
      
        "/SHUTDOWN"
      
      ;
    
      
          21:  
      
      ?
    
      
          22:  
      
      
        // the shutdown command received
      
    
      
          23:  
      
      
        private
      
       boolean shutdown = 
      
        false
      
      ;
    
      
          24:  
      
      ?
    
      
          25:  
      
      
        public
      
      
        static
      
      
        void
      
       main(String[] args) {
    
      
          26:  
      
              HttpServer server = 
      
        new
      
       HttpServer();
    
      
          27:  
      
              server.await();
    
      
          28:  
      
          }
    
      
          29:  
      
      ?
    
      
          30:  
      
      
        public
      
      
        void
      
       await() {
    
      
          31:  
      
              ServerSocket serverSocket = 
      
        null
      
      ;
    
      
          32:  
      
      
        int
      
       port = 8080;
    
      
          33:  
      
      
        try
      
       {
    
      
          34:  
      
                  serverSocket = 
      
        new
      
       ServerSocket(port, 1, InetAddress.getByName(
      
        "127.0.0.1"
      
      ));
    
      
          35:  
      
              } 
      
        catch
      
      (IOException e) {
    
      
          36:  
      
                  e.printStackTrace();
    
      
          37:  
      
                  System.exit(1);
    
      
          38:  
      
              }
    
      
          39:  
      
      
        // 輪詢是否有請(qǐng)求進(jìn)來(lái)
      
    
      
          40:  
      
      
        while
      
      (!shutdown) {
    
      
          41:  
      
                  Socket socket = 
      
        null
      
      ;
    
      
          42:  
      
                  InputStream input = 
      
        null
      
      ;
    
      
          43:  
      
                  OutputStream output = 
      
        null
      
      ;
    
      
          44:  
      
      
        try
      
       {
    
      
          45:  
      
                      socket = serverSocket.accept();
    
      
          46:  
      
                      input = socket.getInputStream();
    
      
          47:  
      
                      output = socket.getOutputStream();
    
      
          48:  
      
      
        // create Request object and parse
      
    
      
          49:  
      
                      Request request = 
      
        new
      
       Request(input);
    
      
          50:  
      
                      request.parse();
    
      
          51:  
      
      
        // create Response object
      
    
      
          52:  
      
                      Response response = 
      
        new
      
       Response(output);
    
      
          53:  
      
                      response.setRequest(request);
    
      
          54:  
      
                      response.sendStaticResource();
    
      
          55:  
      
      
        // Close the socket
      
    
      
          56:  
      
                      socket.close();
    
      
          57:  
      
      
        // check if the previous URI is a shutdown command
      
    
      
          58:  
      
                      shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
    
      
          59:  
      
                  } 
      
        catch
      
      (Exception e) {
    
      
          60:  
      
                      e.printStackTrace();
    
      
          61:  
      
      
        continue
      
      ;
    
      
          62:  
      
                  }
    
      
          63:  
      
              }
    
      
          64:  
      
          }
    
      
          65:  
      
      }
    

4.2 Request.java

      
           1:  
      
      package ex01.pyrmont;
    
      
           2:  
      
      ?
    
      
           3:  
      
      import java.io.IOException;
    
      
           4:  
      
      import java.io.InputStream;
    
      
           5:  
      
      ?
    
      
           6:  
      
      
        public
      
      
        class
      
       Request {
    
      
           7:  
      
      ?
    
      
           8:  
      
      
        private
      
       InputStream input;
    
      
           9:  
      
      ?
    
      
          10:  
      
      
        private
      
       String uri;
    
      
          11:  
      
      ?
    
      
          12:  
      
      
        public
      
       Request(InputStream input) {
    
      
          13:  
      
      
        this
      
      .input = input;
    
      
          14:  
      
          }
    
      
          15:  
      
      ?
    
      
          16:  
      
      
        public
      
      
        void
      
       parse() {
    
      
          17:  
      
      
        // Read a set of characters from the socket
      
    
      
          18:  
      
              StringBuffer request = 
      
        new
      
       StringBuffer(2048);
    
      
          19:  
      
      
        int
      
       i;
    
      
          20:  
      
      
        byte
      
      [] buffer = 
      
        new
      
      
        byte
      
      [2048];
    
      
          21:  
      
      
        try
      
       {
    
      
          22:  
      
                  i = input.read(buffer);
    
      
          23:  
      
              } 
      
        catch
      
      (IOException e) {
    
      
          24:  
      
                  e.printStackTrace();
    
      
          25:  
      
                  i = -1;
    
      
          26:  
      
              }
    
      
          27:  
      
      
        for
      
      (
      
        int
      
       j = 0; j < i; j++) {
    
      
          28:  
      
                  request.append((
      
        char
      
      )buffer[j]);
    
      
          29:  
      
              }
    
      
          30:  
      
              System.
      
        out
      
      .print(request.toString());
    
      
          31:  
      
              uri = parseUri(request.toString());
    
      
          32:  
      
          }
    
      
          33:  
      
      ?
    
      
          34:  
      
      
        private
      
       String parseUri(String requestString) {
    
      
          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:  
      
      
        return
      
       uri;
    
      
          47:  
      
          }
    
      
          48:  
      
      }
    
      
          49:  
      
      ?
    

4.3 Response.java

      
           1:  
      
      package ex01.pyrmont;
    
      
           2:  
      
      ?
    
      
           3:  
      
      import java.io.File;
    
      
           4:  
      
      import java.io.FileInputStream;
    
      
           5:  
      
      import java.io.IOException;
    
      
           6:  
      
      import java.io.OutputStream;
    
      
           7:  
      
      ?
    
      
           8:  
      
      
        /*
      
    
      
           9:  
      
      
        * HTTP Response = Status-Line (( general-header | response-header |
      
    
      
          10:  
      
      
        * entity-header ) CRLF) CRLF [ message-body ] Status-Line = HTTP-Version SP
      
    
      
          11:  
      
      
        * Status-Code SP Reason-Phrase CRLF
      
    
      
          12:  
      
      
        */
      
    
      
          13:  
      
      
        public
      
      
        class
      
       Response {
    
      
          14:  
      
      ?
    
      
          15:  
      
      
        private
      
      
        static
      
       final 
      
        int
      
       BUFFER_SIZE = 1024;
    
      
          16:  
      
      ?
    
      
          17:  
      
          Request request;
    
      
          18:  
      
      ?
    
      
          19:  
      
          OutputStream output;
    
      
          20:  
      
      ?
    
      
          21:  
      
      
        public
      
       Response(OutputStream output) {
    
      
          22:  
      
      
        this
      
      .output = output;
    
      
          23:  
      
          }
    
      
          24:  
      
      ?
    
      
          25:  
      
      
        public
      
      
        void
      
       setRequest(Request request) {
    
      
          26:  
      
      
        this
      
      .request = request;
    
      
          27:  
      
          }
    
      
          28:  
      
      ?
    
      
          29:  
      
      
        public
      
      
        void
      
       sendStaticResource() throws IOException {
    
      
          30:  
      
      
        byte
      
      [] bytes = 
      
        new
      
      
        byte
      
      [BUFFER_SIZE];
    
      
          31:  
      
              FileInputStream fis = 
      
        null
      
      ;
    
      
          32:  
      
      
        try
      
       {
    
      
          33:  
      
                  File file = 
      
        new
      
       File(HttpServer.WEB_ROOT, request.getUri());
    
      
          34:  
      
      
        if
      
      (file.exists()) {
    
      
          35:  
      
                      fis = 
      
        new
      
       FileInputStream(file);
    
      
          36:  
      
      
        int
      
       ch = fis.read(bytes, 0, BUFFER_SIZE);
    
      
          37:  
      
      
        while
      
      (ch != -1) {
    
      
          38:  
      
                          output.write(bytes, 0, ch);
    
      
          39:  
      
                          ch = fis.read(bytes, 0, BUFFER_SIZE);
    
      
          40:  
      
                      }
    
      
          41:  
      
                  } 
      
        else
      
       {
    
      
          42:  
      
      
        // file not found
      
    
      
          43:  
      
                      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>"
      
      ;
    
      
          44:  
      
                      output.write(errorMessage.getBytes());
    
      
          45:  
      
                  }
    
      
          46:  
      
              } 
      
        catch
      
      (Exception e) {
    
      
          47:  
      
      
        // thrown if cannot instantiate a File object
      
    
      
          48:  
      
                  System.
      
        out
      
      .println(e.toString());
    
      
          49:  
      
              } 
      
        finally
      
       {
    
      
          50:  
      
      
        if
      
      (fis != 
      
        null
      
      )
    
      
          51:  
      
                      fis.close();
    
      
          52:  
      
              }
    
      
          53:  
      
          }
    
      
          54:  
      
      }
    
      
          55:  
      
      ?
    


5. 總結(jié)

???? 本文講解了web server的基本原理,同時(shí)代碼貼出來(lái)了一個(gè)粗糙山寨的web server。它只有三個(gè)類構(gòu)成,當(dāng)然不是全功能的,不過(guò)呢,畢竟剛開(kāi)始,我們會(huì)不斷的逐步完善這個(gè)web server,到本系列結(jié)束時(shí),基本上就有一個(gè)完整的web server了。

?

文檔信息

Tomcat是怎么工作的(2) -- 動(dòng)手實(shí)現(xiàn)山寨版的簡(jiǎn)單Web Server


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

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

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

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

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

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

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 亚洲中午字幕 | 亚洲精品9999久久久久 | 图片专区亚洲 欧美 另类 | 国产精品久久久久久久久免费观看 | 手机在线看片国产日韩生活片 | 老司机精品久久最新免费 | 九月婷婷亚洲综合在线 | 四虎影视永久在线观看 | 99热久久这里只有精品9 | 国产欧美日韩亚洲 | 久久精品国产亚洲综合色 | 91在线公开视频 | 色偷偷亚洲 | 久久er国产精品免费观看2 | 亚洲欧美不卡中文字幕 | 国产一区二区三区亚洲综合 | 国产一区二区成人 | 免费观看呢日本天堂视频 | 成人影院观看 | 天天天天躁天天天天碰 | 国产免费观看a大片的网站 国产免费精彩视频 | 久久99国产精品久久99无号码 | 狠狠色丁香婷婷综合小时婷婷 | 超激情碰碰碰啪在线视频 | 国产精品k| 日日日干干干 | 久久亚洲精品专区蓝色区 | 亚洲区一区 | 天天干天天操天天操 | bbw下身丰满18ⅹxxⅹ | 香蕉视频网站免费观视频 | 亚洲va国产日韩欧美精品色婷婷 | 手机看片日韩欧美 | 中文字幕一区二区精品区 | 免费看一区二区三区 | 国产福利在线免费观看 | 欧美一区二区三区视频在线观看 | 国产成人免费网站在线观看 | 午夜私人 | 伊人久热这里只有精品视频99 | 国产精品久久久久影院色 |