Eco cliente-servidor con sockets UDP en Java (DatagramSocket)
Resumen
El documento explica cómo implementar un sistema de comunicación de eco entre un cliente y un servidor usando el protocolo UDP y la clase DatagramSocket de Java. Se presentan el código del cliente, que envía mensajes y espera la respuesta hasta recibir "fin", y el del servidor, que escucha en bucle infinito y devuelve cada mensaje recibido.
Puntos clave
- UDP es un protocolo sin conexión que se gestiona en Java con DatagramSocket y DatagramPacket.
- El cliente crea un DatagramSocket sin argumentos, envía un datagrama a la IP y puerto del servidor y espera la respuesta.
- El cliente termina la comunicación al escribir "fin", cerrando el socket.
- El servidor se enlaza a una dirección con InetSocketAddress y permanece en un bucle infinito recibiendo y reenviando datagramas.
- Para construir el String recibido se usa la longitud real del paquete (getLength()) en lugar de la longitud del buffer.
Ejercicio 3: Comunicación Cliente-Servidor mediante UDP
Este documento presenta la implementación en Java de un sistema de comunicación de eco (echo) utilizando el protocolo UDP a través de la clase DatagramSocket.
1. Clase Cliente
El cliente se encarga de enviar mensajes al servidor y esperar la respuesta de eco, cerrando la conexión al enviar el mensaje "fin".
Código Java del Cliente
public class Cliente {
// Se asume que este código se ejecuta dentro de un método main o similar
public static void main(String[] args) {
try {
// Le pasamos la IP y el puerto de conexión, y el bind se realiza de forma implícita:
InetAddress addr = InetAddress.getByName(HOST); // Crea la InetAddress
DatagramSocket ds = new DatagramSocket(); // Crea el socket
Scanner scanner = new Scanner(System.in);
String mensaje;
do {
System.out.print("Escriba el mensaje que desea enviar al servidor: ");
mensaje = scanner.next(); // Escribimos el mensaje que deseamos enviar
// DatagramPacket datagrama = new DatagramPacket(mensaje, longitud); // Datagrama que se usa para recibir
// Datagrama que se usa para enviar
DatagramPacket datagramaEnviar = new DatagramPacket(
mensaje.getBytes(),
mensaje.getBytes().length,
addr,
PUERTO
); // Crea el datagrama
ds.send(datagramaEnviar); // Se envía el datagrama
// Para recibir el mensaje
int longitud = 100; // Longitud máxima del mensaje
byte[] mensajeRecibido = new byte[longitud]; // Array de bytes donde almacenar el mensaje
DatagramPacket datagramaRecibir = new DatagramPacket(mensajeRecibido, longitud);
ds.receive(datagramaRecibir);
if (mensaje.equalsIgnoreCase("fin")) {
System.out.println("FIN DE COMUNICACIÓN :)");
ds.close();
} else {
// Se utiliza la longitud real del paquete recibido para construir el String
String ecoMensaje = new String(datagramaRecibir.getData(), 0, datagramaRecibir.getLength()).trim();
System.out.println(">>ECO: " + ecoMensaje);
}
} while (!mensaje.equalsIgnoreCase("fin"));
scanner.close();
} catch (IOException e) {
System.err.println("Error al conectarse con el socket del servidor.");
System.out.println(e.getMessage()); // Ejemplo: Connection refused: connect
}
}
}
2. Clase Servidor
El servidor se mantiene en un bucle infinito, esperando peticiones de clientes, recibiendo el mensaje y enviándolo de vuelta como eco.
Código Java del Servidor
public class Servidor {
public static void main(String[] args) {
try {
System.out.println("Esperando una petición del socket cliente...");
// Le pasamos la IP y el puerto de conexión, y el bind se realiza de forma implícita:
InetSocketAddress addr = new InetSocketAddress(HOST, PUERTO); // Incluye el bind
// Nota: InetSocketAddress en el servidor se usa porque es como abrir una puerta con una dirección a la que los clientes se conectan.
DatagramSocket ds = new DatagramSocket(addr); // Crea el socket
while(true) {
int longitud = 100; // Longitud máxima del mensaje
byte[] mensaje = new byte[longitud]; // Array de bytes donde almacenar el mensaje
// Recibe el mensaje del cliente
DatagramPacket datagrama = new DatagramPacket(mensaje, longitud); // Se crea el datagrama
ds.receive(datagrama); // Se carga en el datagrama el mensaje recibido
// Se puede reutilizar el Datagrama, y en receive se puede usar datagrama.getData()
// Lo convierto a String, usando la longitud real del paquete recibido
String mensajeRecibido = new String(datagrama.getData(), 0, datagrama.getLength()).trim();
// Para enviar de vuelta lo que recibo (Eco)
System.out.println("Mensaje recibido: " + mensajeRecibido );
// Envía el datagrama (que ahora contiene la dirección de retorno del cliente)
ds.send(datagrama);
if(mensajeRecibido.equalsIgnoreCase("fin")) {
// Nota: En UDP, el servidor generalmente sigue escuchando, a menos que se fuerce el cierre.
System.out.println("Cliente ha enviado 'fin'. El servidor sigue activo.");
// ds.close(); // Cierra la conexión si se desea terminar el servidor
}
}
} catch (IOException e) {
System.err.println("Error al crear el socket del servidor.");
e.printStackTrace();
}
}
}
Descargar
PDF Word HTMLPreguntas frecuentes
¿Qué clase se usa para comunicar con UDP en Java?
En el documento se usa DatagramSocket para enviar y recibir, y DatagramPacket para encapsular los datos junto con la dirección y el puerto.
¿Cómo sabe el servidor a qué cliente responder?
Al recibir el datagrama, este contiene la dirección y el puerto de origen del cliente, por lo que el servidor puede reenviarlo directamente con ds.send(datagrama).
¿Por qué se usa getLength() al convertir el mensaje a String?
Porque el buffer tiene una longitud fija de 100 bytes y getLength() indica cuántos bytes contiene realmente el paquete recibido, evitando datos sobrantes.
Ponte a prueba
Tarjetas de repaso
Pulsa una tarjeta para ver la respuesta.
Test
Preguntas generadas con IA a partir del documento: comprueba las respuestas con el texto.