我们来看一下如何编写HTTP Server。一个HTTP Server本质上是一个TCP服务器,我们先用TCP编程的多线程实现的服务器端框架:
package com.sun.zuul.http;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class HttpServer {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(8080);
System.out.println(" 监听连接: ");
for (;;) {
Socket socket = ss.accept();
Thread t = new Handler(socket);
t.start();
}
}
}
class Handler extends Thread {
private Socket socket;
public Handler(Socket sock) {
this.socket = sock;
}
@Override
public void run() {
// getInputStream():如果该请求带有HTTP Body,该方法将打开一个输入流用于读取Body;
try (InputStream input = this.socket.getInputStream()) {
try (OutputStream output = this.socket.getOutputStream()) {
handler(input, output);
}
} catch (IOException e) {
try {
this.socket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
System.out.println("client disconnected.");
}
}
// 只需要在handle()方法中,用Reader读取HTTP请求,用Writer发送HTTP响应,即可实现一个最简单的HTTP服务器。编写代码如下:
public void handler(InputStream input, OutputStream output) {
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8));
// TODO 处理HTTP 请求
boolean requestOk = false;
try {
String first = reader.readLine();
if (first.startsWith("GET / HTTP/1.")) {
requestOk = true;
}
// 读取请求信息,默认GET 请求
String head = null;
for (;;) {
head = reader.readLine();
if (head == null) { // 读取到空行时, HTTP Header读取完毕
break;
}
System.out.println(head);
}
System.out.println(requestOk ? "Response OK" : "Response Error");
if (!requestOk) {
// 返回错误码
writer.write("HTTP/1.0 404 Not Found\r\n");
writer.write("Content-Length: 0\r\n");
writer.write("\r\n");
// 及时刷出缓存
writer.flush();
} else{
// 返回成功信息
String data = "<html><body><h1>Hello, world!</h1></body></html>";
int len = data.getBytes(StandardCharsets.UTF_8).length;
writer.write("HTTP/1.0 200 OK\r\n");
writer.write("Connection: close\r\n");
writer.write("Content-Type: text/html\r\n");
writer.write("Content-Length: " + len + "\r\n");
writer.write("\r\n"); // 空行标识Header和Body的分隔
writer.write(data);
writer.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}