====== 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: * Escucha en un puerto con un [[https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/net/ServerSocket.html|ServerSocket]].\\ \\ * 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

Hola

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 = "

Hello from HTTP Server!

"; 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!"**