Web 伺服器基於 Client/Server 模型,透過 HTTP 協定(基於 TCP/IP)通訊。核心四步驟:
GET /index.html HTTP/1.0)HTTP/1.0 200 OK // 狀態行:版本、狀態碼、原因片語
MIME_Version: 1.0 // MIME 版本
Content_Type: text/html // 內容類型(MIME Type)
Content_Length: 1234 // 實體內容長度(位元組)
// 空行分隔標頭與實體
<html>...</html> // 實體內容
import java.io.*;
import java.net.*;
public class WebServer {
public static void main(String[] args) throws IOException {
int port = 8080;
ServerSocket server = new ServerSocket(port);
System.out.println("Web Server listening on port " + port);
int counter = 1;
while (true) {
Socket client = server.accept();
new ConnectionThread(client, counter++).start();
}
}
}
class ConnectionThread extends Thread {
private Socket client;
private int id;
public ConnectionThread(Socket client, int id) {
this.client = client;
this.id = id;
}
public void run() {
try {
PrintStream out = new PrintStream(client.getOutputStream());
DataInputStream in = new DataInputStream(client.getInputStream());
String requestLine = in.readLine(); // 讀取請求行
System.out.println("Request " + id + ": " + requestLine);
if (isGetRequest(requestLine)) {
String filename = extractFilename(requestLine);
File file = new File(filename);
if (file.exists() && file.isFile()) {
sendFile(out, file);
} else {
send404(out);
}
}
client.close();
} catch (IOException e) {
System.err.println("Connection " + id + " error: " + e);
}
}
private boolean isGetRequest(String line) {
return line != null && line.length() > 3 && line.substring(0, 3).equalsIgnoreCase("GET");
}
private String extractFilename(String line) {
int firstSpace = line.indexOf(' ');
int secondSpace = line.indexOf(' ', firstSpace + 1);
String path = line.substring(firstSpace + 1, secondSpace);
if (path.startsWith("/")) path = path.substring(1);
return path.isEmpty() ? "index.html" : path;
}
private void sendFile(PrintStream out, File file) throws IOException {
out.println("HTTP/1.0 200 OK");
out.println("MIME_Version: 1.0");
out.println("Content_Type: text/html");
out.println("Content_Length: " + file.length());
out.println(); // 關鍵空行
byte[] buffer = new byte[(int) file.length()];
new DataInputStream(new FileInputStream(file)).readFully(buffer);
out.write(buffer);
out.flush();
}
private void send404(PrintStream out) {
String body = "404 Not Found "
+ "Error 404 - File Not Found
";
out.println("HTTP/1.0 404 Not Found");
out.println("Content_Type: text/html");
out.println("Content_Length: " + body.length());
out.println();
out.println(body);
out.flush();
}
}
javac WebServer.javaindex.html 置於同目錄java WebServerhttps://localhost:8080/index.htmlContent-TypeContent-Length 讀取請求實體ETag/Last-Modified 搭配 304 Not ModifiedSSLServerSocket 支援加密傳輸Selector + ServerSocketChannel 處理高併發Host 標頭支援多域名手寫伺服器適合教學與嵌入式場景。生產環境建議使用成熟方案:Jetty、Undertow、Tomcat、Netty 等,提供完整 Servlet 規範支援、連線池、安全性、監控、熱部署等企業級特性。