首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 經典實戰:從零手寫一個簡易多執行緒 Web 伺服器

     編輯:Java 相關知識

理解 HTTP 協議與 Socket 通訊的最佳方式,莫過於親手實作一個 Web 伺服器。本例展示一個基於 Java Socket 的多執行緒 HTTP 伺服器核心架構,包含請求解析、靜態檔案服務、錯誤處理與資源釋放等關鍵環節,是學習網路程式設計的絕佳教材。

核心架構:三大組件協作

伺服器採用經典的「主執行緒監聽 + 工作執行緒處理」模型,核心類別職責劃分清晰:

  • WebServer (主類):啟動 ServerSocket 監聽 8000 連接埠,循環 accept() 等待客戶端連線,為每個連線建立 WebThread 處理。
  • Request (請求解析器):讀取 Socket 輸入流,解析 HTTP 請求行,提取請求的資源路徑 (URI)。
  • Response (回應生成器):根據請求路徑讀取本地檔案,構建符合 HTTP/1.1 規範的回應報文(含狀態行、標頭、實體內容)並寫入輸出流。

關鍵程式碼走讀

請求解析:提取 URI

public String parse() {
    StringBuffer requestStr = new StringBuffer(2048);
    byte[] buffer = new byte[2048];
    int i = in.read(buffer);
    for (int j = 0; j < i; j++) requestStr.append((char) buffer[j]);
    return getUri(requestStr.toString());
}

private String getUri(String requestString) {
    int index1 = requestString.indexOf(' ');
    int index2 = requestString.indexOf(' ', index1 + 1);
    return (index1 != -1 && index2 > index1) ? requestString.substring(index1 + 1, index2) : null;
}

簡單粗暴地讀取首包資料,以空格分隔提取 URI(如 /index.html),滿足教學演示需求。生產環境需完整解析 Header、Body 並處理分包/黏包問題。

回應生成:檔案服務與 404 處理

public void Send(String ref) throws IOException {
    File file = new File(WebServer.WEBROOT, ref);
    if (file.exists()) {
        FileInputStream fis = new FileInputStream(file);
        int ch = fis.read(bytes, 0, 2048);
        String sBody = new String(bytes, 0, ch); // 注意:此處原碼有 bug,應指定長度
        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());
    }
}

讀取檔案內容構建 200 OK 回應,檔案不存在回 404。注意:new String(bytes,0) 未指定長度會讀取陣列殘留垃圾資料,正確寫法為 new String(bytes, 0, ch)。此外,僅支援 text/html,實際應根據副檔名設定 MIME 類型。

多執行緒處理模型

class WebThread extends Thread {
    public void run() {
        try {
            Request rq = new Request(sk.getInputStream());
            String sURL = rq.parse();
            if (sURL.equals("/")) sURL = WebServer.defaultPage;
            new Response(sk.getOutputStream()).Send(sURL);
        } finally {
            // 關閉 in, out, socket
        }
    }
}

每個連線獨立一執行緒,互不阻塞,實現併發服務。生產級伺服器會改用執行緒池(ExecutorService)避免執行緒耗盡,並引入 NIO 非阻塞 IO 提升擴展性。

啟動與測試

編譯後執行 java WebServer ./webroot 指定靜態資源根目錄。瀏覽器訪問 https://localhost:8000/ 即可看到 index.htm 內容。這個簡易伺服器雖功能有限,但完整展示了 HTTP 伺服器的靈魂:Socket 監聽 → 協議解析 → 資源定位 → 回應構建 → 連線關閉。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved