Múltiples clientes con hilos
Para atender a múltiples clientes simultáneamente, el servidor usa un hilo dedicado para cada conexión. El bucle principal del servidor llama a accept() indefinidamente, y por cada cliente que se conecta lanza un nuevo Thread:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Servidor {
public static void main(String args[]) throws IOException {
ServerSocket servidor;
servidor = new ServerSocket(6000);
System.out.println("Servidor iniciado...");
while (true) {
Socket cliente = new Socket();
cliente = servidor.accept();
HiloServidor hilo = new HiloServidor(cliente);
hilo.start();
}
}
}
La clase HiloServidor extiende Thread y gestiona la comunicación con el cliente en su método run().
Sockets UDP
A diferencia de TCP, UDP es un protocolo no orientado a conexión. Los paquetes contienen de forma explícita la dirección IP y el puerto de destino, lo que los hace más ligeros pero sin garantía de entrega ni orden.
Clase DatagramPacket
Representa un paquete de datos UDP.
| Constructor / Método | Descripción |
|---|---|
DatagramPacket(byte[] buf, int length) |
Para recibir datos |
DatagramPacket(byte[] buf, int length, InetAddress addr, int port) |
Para enviar datos |
int getLength() |
Longitud de los datos recibidos |
int getPort() |
Puerto de origen del paquete |
InetAddress getAddress() |
Dirección IP de origen |
byte[] getData() |
Contenido del paquete |
Clase DatagramSocket
Proporciona soporte para el envío y recepción de datagramas UDP.
| Constructor / Método | Descripción |
|---|---|
DatagramSocket(int port) |
Crea un socket en el puerto indicado |
DatagramSocket() |
Crea un socket en un puerto disponible |
void send(DatagramPacket p) |
Envía un datagrama |
void receive(DatagramPacket p) |
Recibe un datagrama (bloqueante) |
void close() |
Cierra el socket |
Ejemplo: comunicación UDP
ServidorUDP.java
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class ServidorUDP {
public static void main(String[] argv) throws Exception {
byte[] bufer = new byte[1024];
DatagramSocket socket = new DatagramSocket(12345);
System.out.println("Esperando Datagrama ................");
DatagramPacket recibo = new DatagramPacket(bufer, bufer.length);
socket.receive(recibo);
int bytesRec = recibo.getLength();
String paquete = new String(recibo.getData());
System.out.println("Número de Bytes recibidos: " + bytesRec);
System.out.println("Contenido del Paquete : " + paquete.trim());
System.out.println("Puerto origen del mensaje: " + recibo.getPort());
System.out.println("IP de origen : " + recibo.getAddress().getHostAddress());
System.out.println("Puerto destino del mensaje: " + socket.getLocalPort());
socket.close();
}
}
ClienteUDP.java
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class ClienteUDP {
public static void main(String[] argv) throws Exception {
InetAddress destino = InetAddress.getLocalHost();
int port = 12345;
byte[] mensaje = new byte[1024];
String Saludo = "Enviando Saludos !!";
mensaje = Saludo.getBytes();
DatagramPacket envio = new DatagramPacket(mensaje, mensaje.length, destino, port);
DatagramSocket socket = new DatagramSocket(34567);
System.out.println("Enviando Datagrama de longitud: " + mensaje.length);
System.out.println("Host destino : " + destino.getHostName());
System.out.println("IP Destino : " + destino.getHostAddress());
System.out.println("Puerto local del socket: " + socket.getLocalPort());
System.out.println("Puerto al que envio: " + envio.getPort());
socket.send(envio);
socket.close();
}
}
Sockets Multicast
MulticastSocket permite enviar un paquete a múltiples destinatarios simultáneamente. Los clientes se suscriben a un grupo multicast (dirección de clase D, rango 224.0.0.0 – 239.255.255.255). Cuando el servidor envía al grupo, todos los clientes suscritos reciben el mensaje.
ServidorMC.java
import java.io.*;
import java.net.*;
public class ServidorMC {
public static void main(String args[]) throws Exception {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
MulticastSocket ms = new MulticastSocket();
int Puerto = 12345;
InetAddress grupo = InetAddress.getByName("225.0.0.1");
String cadena = "";
while (!cadena.trim().equals("*")) {
System.out.print("Datos a enviar al grupo: ");
cadena = in.readLine();
DatagramPacket paquete = new DatagramPacket(cadena.getBytes(), cadena.length(), grupo, Puerto);
ms.send(paquete);
}
ms.close();
System.out.println("Socket cerrado...");
}
}
ClienteMC.java
import java.io.*;
import java.net.*;
public class ClienteMC {
public static void main(String args[]) throws Exception {
int Puerto = 12345;
MulticastSocket ms = new MulticastSocket(Puerto);
InetAddress grupo = InetAddress.getByName("225.0.0.1");
ms.joinGroup(grupo);
String msg = "";
while (!msg.trim().equals("*")) {
byte[] buf = new byte[1000];
DatagramPacket paquete = new DatagramPacket(buf, buf.length);
ms.receive(paquete);
msg = new String(paquete.getData());
System.out.println("Recibo: " + msg.trim());
}
ms.leaveGroup(grupo);
ms.close();
System.out.println("Socket cerrado...");
}
}
El servidor lee líneas de la consola y las envía al grupo hasta que se introduce *. Los clientes se unen al grupo con joinGroup() y reciben los mensajes hasta que llega el asterisco.