Programación de Red y Sockets en Java

Capítulo 9: Programación de Red y Sockets en Java

Compartir

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.


Compartir

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *