【HTTP協議其實很簡單】03.自己寫一個微型靜態Web服務器

自己做一個微型靜態Web服務器

這一篇簡單粗暴一點,先上乾貨,看代碼註釋

JDK版本:1.8

實現自定義錯誤頁、404頁。

package com.hawkon;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Date;

public class MyServer {
    public static String HOME_DIR = "d:/home";  //定義服務器默認的文件夾在哪裏
    public static String NOT_FOUND_FILE = "d:/home/404.html"; //定義404錯誤頁
    public static String ERR_FILE = "d:/home/err.html"; //定義500錯誤頁
    public static String DEFAULT_FILE = "/index.html"; //定義默認頁面

    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8009); //定義端口
        while (true) { //循環是不斷的接受新的請求
            Socket socket = serverSocket.accept(); //當服務器運行起來沒有請求的時候會在這裏等待
            InputStream is = socket.getInputStream(); //創建一個輸入流
            InputStreamReader sr = new InputStreamReader(is); //過渡代碼主要是爲下一行創建對象
            BufferedReader br = new BufferedReader(sr); //創建BufferedReader對象,在本文中採用一行一行的讀的方式,比較方便。
            try {
                String request = "";
                request = br.readLine(); //只讀取了第一行,後面報頭本文暫時沒用。
                System.out.println("request:");
                System.out.println(request); //輸出一下請求的報頭
                String[] arr = request.split(" "); //拆分出第一行的三部分內容
                do { //循環是爲了把剩下的請求內容讀完,否則會產生異常
                    request=br.readLine();
                    System.out.println(request); //把全部報頭都輸出
                }while(!request.equals(""));
                if (arr.length != 3 || !arr[0].equals("GET")) { //如果不是GET請求,拆分出的第一行也不是三部分內容直接返回錯誤頁
                    outPutFile(ERR_FILE, socket.getOutputStream(), 500);
                } else {
                    String path = arr[1]; //取出請求的資源路徑
                    if(path.equals("/")) //如果請求的內容沒有指定文件,則返回默認的頁面
                        path=DEFAULT_FILE;
                    if (Files.exists(Paths.get(HOME_DIR + path))) { //判斷文件是否存在 ,如果不存在,返回404頁面
                        outPutFile(HOME_DIR + path, socket.getOutputStream(), 200);
                    } else { //如果文件不存在,返回404頁面
                        outPutFile(NOT_FOUND_FILE, socket.getOutputStream(), 404);
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace(); //輸出異常信息
            } finally {
                br.close();
                sr.close();
                is.close();
            }
        }
    }

    public static void outPutFile(String fileName, OutputStream os, int status) throws IOException {
        System.out.println("response:");
        System.out.println(fileName);
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("HTTP/1.1 " + status + " OK\r\n"); //輸出狀態碼
        stringBuilder.append("Date: " + (new Date()).toString() + "\r\n");
        stringBuilder.append("Server: MyServer 0.0.1\r\n");  //代表服務器的軟件名稱
        stringBuilder.append("X-Powered-By: Hawkon\r\n");    //這行可以換成你的英文名,看起來會有點diao
        stringBuilder.append("Keep-Alive: timeout=5, max=100\r\n");
        stringBuilder.append("Connection: Keep-Alive\r\n");
        stringBuilder.append("Content-Type: text/html;charset=utf-8\r\n"); //字符串編碼
        stringBuilder.append("\r\n");//多輸出一個空行,用來分割報頭和報體,HTTP協議要求
        FileInputStream fis = new FileInputStream(fileName);
        byte[] bytes = new byte[1024];
        int len;
        os.write(stringBuilder.toString().getBytes("UTF-8"));  //輸出響應報頭
        while ((len = fis.read(bytes)) != -1) { //輸出文件內容
            os.write(bytes, 0, len);
        }
        os.flush();
        os.close();
        fis.close();
    }
}


下圖是請求響應的報頭信息。

image

瀏覽器運行的情況
image

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章