02 - Servidor HTTP
Servidor HTTP
HTTP es un protocolo de aplicación que funciona encima de TCP. Cuando escribimos un servidor HTTP, en el fondo estamos abriendo un socket TCP, recibiendo la petición y devolviendo una respuesta siguiendo el formato que dicta el protocolo HTTP.
En este caso, vamos a construir un servidor muy básico que:
- Acepta una conexión de un cliente (normalmente un navegador).
- Lee la petición HTTP (cabeceras y línea de petición).
- Devuelve una respuesta HTTP con código 200 y un pequeño HTML.
Anatomía de una petición HTTP
Cuando un navegador solicita una página, envía algo parecido a:
GET / HTTP/1.1 Host: localhost:12345 User-Agent: Mozilla/5.0 ... Accept: text/html [... otras cabeceras ...]
Las cabeceras terminan con una línea vacía (\r\n).
Anatomía de una respuesta HTTP
El servidor debe responder con:
HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 Content-Length: [número de bytes del HTML] Connection: close <html><body><h1>Hola</h1></body></html>
Las cabeceras también terminan con una línea vacía antes del contenido.
Ciclo de vida clásico
Servidor
- new ServerSocket(puerto) → queda “escuchando”.
- accept() (bloqueante) → devuelve un Socket para el navegador.
- Lee la petición (normalmente hasta la línea vacía que separa cabeceras del cuerpo).
- Escribe una respuesta que cumpla el protocolo HTTP.
- Cierra Socket (y luego ServerSocket si termina).
Cliente (navegador)
- Abre conexión TCP al host:puerto.
- Envía petición HTTP (línea de petición + cabeceras).
- Recibe respuesta HTTP y renderiza el HTML.
- Cierra conexión.
Ejemplo
HttpServer
package es.cesguiro.socket; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; public class HttpServer { private final int port = 12345; public void start() { System.out.println("Starting HTTP server on port " + port + "..."); try { System.out.println("HTTP server started. Waiting for requests..."); // Aceptamos UNA conexión de cliente y luego cerramos el servidor (Ejemplo simple) try(Socket socket = new ServerSocket(port).accept()) { System.out.println("Client connected: " + socket.getInetAddress()); // Leer la solicitud HTTP del cliente BufferedReader in = new BufferedReader( new InputStreamReader(socket.getInputStream()) ); String line; while ((line = in.readLine()) != null && !line.isEmpty()) { System.out.println(line); } // HTML a devolver String htmlResponse = "<html><body><h1>Hello from HTTP Server!</h1></body></html>"; byte[] content = htmlResponse.getBytes(StandardCharsets.UTF_8); // Cabeceras de respuesta HTTP String responseHeader = "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html\r\n" + "Connection: close\r\n" + "\r\n"; OutputStream out = socket.getOutputStream(); out.write(responseHeader.getBytes(StandardCharsets.UTF_8)); out.write(content); out.flush(); } catch (IOException e) { System.err.println("Error handling client connection: " + e.getMessage()); } } catch (Exception e) { System.err.println("Error starting HTTP server: " + e.getMessage()); throw new RuntimeException("Failed to start HTTP server", e); } } }
package es.cesguiro.socket; public class Main { public static void main(String[] args) { HttpServer server = new HttpServer(); server.start(); } }
Para probarlo, accede en tu navegador a http://localhost:12345 y debería ver el mensaje “Hello from HTTP Server!”