实现HTTP服务器

53 阅读2分钟

实现一个能处理HTTP请求的服务器

一般来说,浏览器发送的HTTP请求内容包含:

GET /hello HTTP/1.1
Host: www.example.com
User-Agent: curl/7.88.1
Accept: */*

指出了请求的方法GET,主机www.example.com ,路径/hello

对于服务器来说,只需要解析请求,并对浏览器进行响应即可,这里输出响应:

HTTP/1.1 200 OK
Server: Simple HttpServer/1.0
Date: Fri, 07 Jul 2023 23:15:09 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 22
Connection: keep-alive

<h1>Hello, world.</h1>

那么实现HTTP Server的过程实际上就是:

  1. 接收浏览器发送的HTTP请求
  2. 解析HTTP请求
  3. 处理请求
  4. 发送HTTP响应
  5. 不断重复1-4步骤,直到TCP连接关闭

这里可以通过JDK内置的httpserver包实现,它主要提供了以下几个类:

  1. HttpServer: 通过指定IP地址和端口号,定义一个HTTP服务实例
  2. HttpHandler:处理HTTP请求的核心接口,通过实现handler()方法处理请求
  3. HttpExchange:读取HTTP请求的输入类,并将HTTP响应输出给它
public class SimpleHttpServer implements HttpHandler, AutoCloseable {  
  
final Logger logger = LoggerFactory.getLogger(getClass());  
  
public static void main(String[] args) {  
String host = "0.0.0.0";  
int port = 8080;  
try (SimpleHttpServer connector = new SimpleHttpServer(host, port)) {  
for (; ; ) {  
try {  
Thread.sleep(1000);  
} catch (InterruptedException e) {  
break;  
}  
}  
} catch (Exception e) {  
e.printStackTrace();  
}  
}  
  
final HttpServer httpServer;  
final String host;  
final int port;  
  
public SimpleHttpServer(String host, int port) throws IOException {  
this.host = host;  
this.port = port;  
this.httpServer = HttpServer.create(new InetSocketAddress(host, port), 0);  
this.httpServer.createContext("/", this); // 注册路径和处理器  
this.httpServer.start();  
}  
  
@Override  
public void close() {  
this.httpServer.stop(3);  
}  
  
@Override  
public void handle(HttpExchange exchange) throws IOException {  
String method = exchange.getRequestMethod();  
URI uri = exchange.getRequestURI();  
String path = uri.getPath();  
String query = uri.getRawQuery();  
Headers respHeaders = exchange.getResponseHeaders();  
respHeaders.set("Content-Type", "text/html; charset=utf-8");  
// 设置200响应:  
exchange.sendResponseHeaders(200, 0);  
String s = "<h1>Hello, world.</h1><p>" + LocalDateTime.now().withNano(0) + "</p>";  
try (OutputStream out = exchange.getResponseBody()) {  
out.write(s.getBytes(StandardCharsets.UTF_8));  
}  
}  
}

启动服务后,在浏览器中输入localhost:8080就可以看见响应

image.png

总结: 通过JDK内置的httpserver包实现了一个简易的能处理http请求的服务器