En este capítulo, exploraremos la programación de red en Java y cómo utilizar sockets para la comunicación entre aplicaciones a través de una red. Esta es una habilidad esencial para desarrollar aplicaciones que se conectan a servidores, intercambian datos y se comunican a través de Internet.
9.1. Introducción a la Programación de Red
La programación de red en Java implica la creación de aplicaciones que pueden comunicarse a través de redes, ya sea en una red local o a través de Internet. En Java, esto se logra utilizando la API java.net
, que proporciona clases y métodos para trabajar con redes y comunicación.
9.2. Sockets en Java
Los sockets son la base de la comunicación en red en Java. Los sockets permiten la comunicación entre dos máquinas a través de una red utilizando un flujo de datos bidireccional. Hay dos tipos de sockets en Java: sockets de servidor (ServerSocket) y sockets de cliente (Socket).
Ejemplo 9.2.1: Comunicación Básica Cliente-Servidor
A continuación, se muestra un ejemplo simple de un servidor y un cliente que se comunican a través de sockets.
Servidor:
import java.io.*;
import java.net.*;
public class Servidor {
public static void main(String[] args) throws IOException {
int puerto = 12345;
ServerSocket serverSocket = new ServerSocket(puerto);
System.out.println("Servidor esperando conexiones en el puerto " + puerto);
Socket socketCliente = serverSocket.accept();
System.out.println("Cliente conectado desde " + socketCliente.getInetAddress());
// Flujo de entrada y salida para comunicación
PrintWriter out = new PrintWriter(socketCliente.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socketCliente.getInputStream()));
String mensajeCliente;
while ((mensajeCliente = in.readLine()) != null) {
System.out.println("Cliente dice: " + mensajeCliente);
out.println("Respuesta del servidor: " + mensajeCliente);
}
// Cerrar conexiones
in.close();
out.close();
socketCliente.close();
serverSocket.close();
}
}
Cliente:
import java.io.*;
import java.net.*;
public class Cliente {
public static void main(String[] args) throws IOException {
String servidor = "localhost";
int puerto = 12345;
Socket socket = new Socket(servidor, puerto);
// Flujo de entrada y salida para comunicación
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// Enviar mensaje al servidor
out.println("Hola, servidor");
// Recibir respuesta del servidor
String respuestaServidor = in.readLine();
System.out.println("Servidor dice: " + respuestaServidor);
// Cerrar conexiones
in.close();
out.close();
socket.close();
}
}
9.3. Ejercicios de Práctica
Ejercicio 9.3.1: Chat Cliente-Servidor
Desarrolla una aplicación de chat cliente-servidor donde varios clientes pueden conectarse a un servidor y enviarse mensajes entre sí.
Ejercicio 9.3.2: Transferencia de Archivos
Crea una aplicación que permita a los clientes cargar y descargar archivos desde un servidor a través de una conexión de red.
Resumen del Capítulo
La programación de red y el uso de sockets en Java son habilidades esenciales para desarrollar aplicaciones que se comunican a través de una red. En este capítulo, hemos introducido los conceptos básicos y proporcionado un ejemplo de comunicación básica entre un servidor y un cliente. Los ejercicios proporcionados permiten a los lectores practicar y profundizar en su comprensión de la programación de red en Java.
Respuesta ejercicio 9.3.1:
Para resolver el ejercicio de desarrollar una aplicación de chat cliente-servidor en Java donde varios clientes pueden conectarse a un servidor y enviarse mensajes entre sí, sigue estos pasos:
Paso 1: Desarrollo del Servidor de Chat
Primero, desarrolla el servidor de chat que escuchará a los clientes y gestionará las conexiones y los mensajes. Utilizaremos un ServerSocket
para aceptar conexiones de múltiples clientes y un hilo separado para cada cliente.
Servidor de Chat:
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.List;
public class ServidorChat {
private static final int PUERTO = 12345;
private static List<PrintWriter> clientes = new ArrayList<>();
public static void main(String[] args) {
System.out.println("Servidor de chat iniciado en el puerto " + PUERTO);
try (ServerSocket serverSocket = new ServerSocket(PUERTO)) {
while (true) {
new ClienteHandler(serverSocket.accept()).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static class ClienteHandler extends Thread {
private Socket socket;
private PrintWriter out;
public ClienteHandler(Socket socket) {
this.socket = socket;
}
public void run() {
try {
out = new PrintWriter(socket.getOutputStream(), true);
clientes.add(out);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String mensaje;
while ((mensaje = in.readLine()) != null) {
System.out.println("Mensaje recibido: " + mensaje);
for (PrintWriter cliente : clientes) {
cliente.println(mensaje);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
clientes.remove(out);
}
}
}
}
}
Paso 2: Desarrollo del Cliente de Chat
A continuación, desarrolla el cliente de chat que se conectará al servidor y permitirá a los usuarios enviar y recibir mensajes en el chat.
Cliente de Chat:
import java.io.*;
import java.net.*;
public class ClienteChat {
public static void main(String[] args) {
String servidor = "localhost";
int puerto = 12345;
try (Socket socket = new Socket(servidor, puerto);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
System.out.println("Conectado al servidor de chat. Ingrese su nombre:");
String nombre = reader.readLine();
out.println(nombre);
System.out.println("¡Comienza a chatear! Escribe 'salir' para desconectarte.");
Thread mensajeEntrante = new Thread(() -> {
String mensaje;
try {
while ((mensaje = in.readLine()) != null) {
System.out.println(mensaje);
}
} catch (IOException e) {
e.printStackTrace();
}
});
mensajeEntrante.start();
String userInput;
while (true) {
userInput = reader.readLine();
if (userInput.equalsIgnoreCase("salir")) {
break;
}
out.println(nombre + ": " + userInput);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Paso 3: Ejecución del Servidor y los Clientes
Ejecuta al menos un servidor y varios clientes para comenzar a chatear. Los clientes pueden conectarse al servidor y enviar mensajes. El servidor reenviará los mensajes a todos los clientes conectados.
Resultado Esperado:
Los clientes pueden conectarse al servidor, enviar mensajes y recibir mensajes de otros clientes. Esto permite una comunicación de chat en tiempo real entre múltiples clientes.
Este ejercicio demuestra cómo crear una aplicación de chat cliente-servidor en Java donde varios clientes pueden conectarse al servidor y enviarse mensajes entre sí. Puedes personalizar este ejemplo para incluir más características, como nombres de usuario, comandos, etc.
Respuesta ejercicio 9.3.2:
Para crear una aplicación que permita a los clientes cargar y descargar archivos desde un servidor a través de una conexión de red en Java, sigue estos pasos:
Paso 1: Desarrollo del Servidor de Archivos
Primero, desarrolla el servidor de archivos que escuchará a los clientes y gestionará las solicitudes de carga y descarga de archivos. Utilizaremos un ServerSocket
para aceptar conexiones de los clientes y gestionar las operaciones de archivo.
Servidor de Archivos:
import java.io.*;
import java.net.*;
public class ServidorArchivos {
private static final int PUERTO = 12345;
private static final String CARPETA_ARCHIVOS = "archivos/";
public static void main(String[] args) {
System.out.println("Servidor de archivos iniciado en el puerto " + PUERTO);
try (ServerSocket serverSocket = new ServerSocket(PUERTO)) {
while (true) {
Socket socket = serverSocket.accept();
new ClienteHandler(socket).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static class ClienteHandler extends Thread {
private Socket socket;
public ClienteHandler(Socket socket) {
this.socket = socket;
}
public void run() {
try (DataInputStream dis = new DataInputStream(socket.getInputStream());
DataOutputStream dos = new DataOutputStream(socket.getOutputStream())) {
String nombreArchivo = dis.readUTF();
File archivo = new File(CARPETA_ARCHIVOS + nombreArchivo);
if (archivo.exists()) {
dos.writeBoolean(true);
dos.writeLong(archivo.length());
try (FileInputStream fis = new FileInputStream(archivo)) {
byte[] buffer = new byte[4096];
int leidos;
while ((leidos = fis.read(buffer)) > 0) {
dos.write(buffer, 0, leidos);
}
}
} else {
dos.writeBoolean(false);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Paso 2: Desarrollo del Cliente de Archivos
A continuación, desarrolla el cliente de archivos que se conectará al servidor y permitirá a los usuarios cargar y descargar archivos.
Cliente de Archivos:
import java.io.*;
import java.net.*;
public class ClienteArchivos {
public static void main(String[] args) {
String servidor = "localhost";
int puerto = 12345;
try (Socket socket = new Socket(servidor, puerto);
DataInputStream dis = new DataInputStream(socket.getInputStream());
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)) {
System.out.println("Conectado al servidor de archivos.");
while (true) {
System.out.println("1. Descargar archivo");
System.out.println("2. Salir");
System.out.print("Seleccione una opción: ");
int opcion = Integer.parseInt(reader.readLine());
if (opcion == 1) {
System.out.print("Ingrese el nombre del archivo a descargar: ");
String nombreArchivo = reader.readLine();
dos.writeUTF(nombreArchivo);
boolean existe = dis.readBoolean();
if (existe) {
long tamano = dis.readLong();
System.out.println("Descargando archivo...");
FileOutputStream fos = new FileOutputStream(nombreArchivo);
byte[] buffer = new byte[4096];
int leidos;
long recibidos = 0;
while (recibidos < tamano && (leidos = dis.read(buffer, 0, (int) Math.min(buffer.length, tamano - recibidos))) != -1) {
fos.write(buffer, 0, leidos);
recibidos += leidos;
}
fos.close();
System.out.println("Archivo descargado.");
} else {
System.out.println("El archivo no existe en el servidor.");
}
} else if (opcion == 2) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Paso 3: Crear una Carpeta para Archivos
Asegúrate de tener una carpeta llamada «archivos» en la misma ubicación que el servidor y el cliente. Esta carpeta se utiliza para almacenar los archivos que el servidor puede enviar y los archivos que los clientes pueden cargar.
Paso 4: Ejecución del Servidor y los Clientes
Ejecuta el servidor y al menos un cliente para cargar y descargar archivos. Los clientes pueden seleccionar la opción «1» para descargar un archivo o «2» para salir.
Resultado Esperado:
Los clientes pueden cargar y descargar archivos desde el servidor a través de una conexión de red. El servidor gestiona las solicitudes y envía los archivos solicitados a los clientes.
Este ejercicio muestra cómo crear una aplicación de carga y descarga de archivos cliente-servidor en Java. Puedes personalizar este ejemplo para incluir más características, como una interfaz de usuario o autenticación de usuarios.