使用 Java 原生 TCP Socket 实现 HTTP 请求解析和请求分发,是一个理解 HTTP 协议底层原理的好方法。虽然 Java 提供了 HttpServer
类来简化 HTTP 服务器开发,但如果你想从 TCP 层 开始构建一个简单的 HTTP 服务器,可以使用 ServerSocket
和 Socket
实现。
在进行web开发前.我们扩展一下 8.3 Java HTTP-CSDN博客 的内容.实现http请求分发
使用 Java 原生 TCP Socket 实现:
- 接收 HTTP 请求(GET/POST)
- 解析请求头和请求路径
- 根据路径分发请求到不同处理方法
- 返回 HTTP 响应
实现代码
1. 引入基础类
import java.io.*;
import java.net.*;
import java.util.*;
2. 定义处理接口
@FunctionalInterface
interface HttpRequestHandler {
void handle(HttpRequest request, HttpResponse response) throws IOException;
}
3. 定义请求和响应封装类
class HttpRequest {
String method;
String path;
Map<String, String> headers = new HashMap<>();
String body;
public HttpRequest(String method, String path, Map<String, String> headers, String body) {
this.method = method;
this.path = path;
this.headers = headers;
this.body = body;
}
}
class HttpResponse {
private BufferedWriter out;
private OutputStream rawOut;
public HttpResponse(BufferedWriter out, OutputStream rawOut) {
this.out = out;
this.rawOut = rawOut;
}
public void send(int statusCode, String contentType, String responseBody) throws IOException {
String statusLine = statusCode == 200 ? "HTTP/1.1 200 OK" : "HTTP/1.1 404 Not Found";
String response =
statusLine + "\r\n" +
"Content-Type: " + contentType + "\r\n" +
"Content-Length: " + responseBody.length() + "\r\n" +
"Connection: close\r\n" +
"\r\n" +
responseBody;
out.write(response);
out.flush();
}
public void sendFile(int statusCode, String contentType, byte[] fileBytes) throws IOException {
String statusLine = statusCode == 200 ? "HTTP/1.1 200 OK" : "HTTP/1.1 404 Not Found";
String header =
statusLine + "\r\n" +
"Content-Type: " + contentType + "\r\n" +
"Content-Length: " + fileBytes.length + "\r\n" +
"Connection: close\r\n" +
"\r\n";
rawOut.write(header.getBytes());
rawOut.write(fileBytes);
rawOut.flush();
}
}
4. 定义主服务器类
public class SimpleHttpServerUsingTCP {
private static final int PORT = 8080;
private static Map<String, HttpRequestHandler> routeMap = new HashMap<>();
public static void main(String[] args) throws IOException {
routeMap.put("/hello", (req, res) -> {
try {
res.send(200, "text/plain", "Hello, World!");
} catch (IOException e) {
e.printStackTrace();
}
});
routeMap.put("/about", (req, res) -> {
try {
res.send(200, "text/plain", "This is a simple HTTP server using TCP.");
} catch (IOException e) {
e.printStackTrace();
}
});
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println("Server started on port " + PORT);
while (true) {
Socket clientSocket = serverSocket.accept();
handleClient(clientSocket);
}
}
private static void handleClient(Socket socket) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
OutputStream rawOut = socket.getOutputStream();
String line = in.readLine();
if (line == null || line.isEmpty()) return;
System.out.println("Request: " + line);
// 解析请求行
String[] requestLine = line.split(" ");
String method = requestLine[0];
String path = requestLine[1];
// 解析请求头
Map<String, String> headers = new HashMap<>();
while (!(line = in.readLine()).isEmpty()) {
String[] header = line.split(": ");
if (header.length == 2) {
headers.put(header[0], header[1]);
}
}
// 读取请求体(仅处理 POST)
int contentLength = 0;
if (headers.containsKey("Content-Length")) {
contentLength = Integer.parseInt(headers.get("Content-Length"));
}
char[] bodyBuffer = new char[contentLength];
in.read(bodyBuffer, 0, contentLength);
String body = new String(bodyBuffer);
// 构建请求和响应对象
HttpRequest request = new HttpRequest(method, path, headers, body);
HttpResponse response = new HttpResponse(out, rawOut);
// 路由分发
HttpRequestHandler handler = routeMap.get(path);
if (handler != null) {
handler.handle(request, response);
} else {
response.send(404, "text/plain", "404 Not Found");
}
socket.close();
}
}
测试方式
使用浏览器访问:
http://localhost:8080/hello
http://localhost:8080/about
http://localhost:8080/unknown
使用 curl
测试:
curl http://localhost:8080/hello
# 输出: Hello, World!
curl http://localhost:8080/about
# 输出: This is a simple HTTP server using TCP.
curl http://localhost:8080/unknown
# 输出: 404 Not Found
支持 POST 请求(可选扩展)
你可以通过解析请求体,支持 POST 请求,例如:
routeMap.put("/post", (req, res) -> {
System.out.println("Received POST body: " + req.body);
res.send(200, "text/plain", "POST received: " + req.body);
});