最簡單的web伺服器實現(一)

yuntui發表於2016-11-03
tomcat作為web伺服器,想必大家做過web開發的都離不開tomcat了,值得慶幸的是tomcat也是開放原始碼的,最近準備好好琢磨琢磨tomcat的原始碼,還沒開始就已經感覺到不少的未知恐懼了,慢慢來把。
可能我的學習方式比較急功近利,但是這種方式收效也快,自己記得在<<Java程式設計師 上班那點事兒>>裡作者寫過一個最簡單的web伺服器實現,自己在網上也比較了一下其它的版本,還是感覺那本書裡的版本比較好,在此分享出來,因為時間緊,照著書敲了一遍程式碼,竟然發現裡面有一些很細小的錯誤,自己準備在這個基礎上好好改進一把。
首先來看看web伺服器的一些基本原理,我們的實驗是基於socket的,開放了一個指定的埠,然後會啟用對應的執行緒來處理瀏覽器中的請求。如果檔案不存在,會報出404錯誤,否則會解析檔案的內容。
HttpServer類是後臺服務類,會開放對應的埠和socket來處理瀏覽發出的請求。
HttpThread類是接受瀏覽器傳送請求的類,透過Receive和Answer來接受和處理瀏覽器傳送的請求,然後返回到客戶端中。

點選(此處)摺疊或開啟

  1. package new_test;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    public class HttpServer { 
    public static String ROOT="./wwwroot";
    public static String defaultPage="index.html";

        public static void main(String[] args) throws IOException{ 
            
                ServerSocket ss = new ServerSocket(8080); 
                while(true){
                Socket s=ss.accept();
                    System.out.println("Accept Connection...:");                                   
                     new HttpThread(s).start();
                }        
        } 
    }



點選(此處)摺疊或開啟

  1. package new_test;


    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import
    } java.net.Socket;


    public class HttpThread extends Thread {


    private Socket socket;


    public HttpThread(Socket s) {
    this.socket = s;


    public void run() {
    InputStream ins = null;
    OutputStream ous = null;
    try {
    ous = socket.getOutputStream();
    ins = socket.getInputStream();
    Receive rcv = new Receive(ins);
    String sURL = rcv.parse();
    System.out.println("sURL is " + sURL);


    if (sURL.equals("/")) {
    sURL = HttpServer.defaultPage;
    }
    Answer ans = new Answer(ous);
    ans.send(sURL);
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    try {
    if (ins != null) {
    ins.close();
    }
    if (ous != null) {
    ous.close();
    }
    if (socket != null) {
    socket.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }

點選(此處)摺疊或開啟

  1. package new_test;


    import java.io.IOException;
    import java.io.InputStream;


    public class Receive {
    InputStream in = null;


    public Receive(InputStream ins) {
    this.in = ins;
    }


    public String parse() {
    StringBuffer receiveStr = new StringBuffer(2048);
    int i ;
    byte[] buffer = new byte[2048];
    try {
    i = in.read(buffer);
    } catch (IOException e) {
    i = -1;
    }
    for (int j = 0; j < i; j++) {
    receiveStr.append((char)buffer[j]);


    }
    return getUri(receiveStr.toString());
    }


    private String getUri(String receiveStr) {
    int index1, index2;
    System.out.println("receiveStr is " + receiveStr);
    index1 = receiveStr.indexOf(" ");
    if (index1 != -1) {
    index2 = receiveStr.indexOf(" ", index1 + 1);
    if (index2 > index1) {
    return receiveStr.substring(index1 + 1, index2);
    }
    }
    return null;
    }


    }





點選(此處)摺疊或開啟

  1. package new_test;


    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.OutputStream;


    public class Answer {
    OutputStream out = null;


    public Answer(OutputStream ous) {
    this.out = ous;
    }


    public void send(String pageFile) {
    byte[] bytes = new byte[2048];


    FileInputStream fis = null;
    try {
    File file = new File(HttpServer.ROOT, pageFile);
    if (file.exists()) {


    fis = new FileInputStream(file);
    int ch = fis.read(bytes, 0, 2048);
    String sBody = new String(bytes, 0);
    String sendMessage = "HTTP/1.1 200 OK\r\n"
    + "Content-Type:text/html\r\n" + "Content-Length:" + ch
    + "\r\n" + "\r\n" + sBody;
    out.write(sendMessage.getBytes());
    } else {
    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>";
    out.write(errorMessage.getBytes());
    }
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    if (fis != null) {
    try {
    fis.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }


    }


    }


一個簡單呼叫的情況就是,如果不存在對應的頁面會直接丟擲File Not Found的錯誤資訊

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30633755/viewspace-2127784/,如需轉載,請註明出處,否則將追究法律責任。

相關文章