Implementación de Sockets en Java: Ejemplos Prácticos de Servidores y Clientes

Enviado por Chuletator online y clasificado en Informática y Telecomunicaciones

Escrito el en español con un tamaño de 8,84 KB

Implementación de Sockets en Java

A continuación, se presentan diversos ejemplos prácticos para la comunicación entre procesos mediante Sockets en Java, cubriendo desde un juego simple hasta un servidor web básico.

1. Juego de Adivinanza: Cliente y Servidor

Este ejemplo ilustra una comunicación síncrona donde el cliente intenta adivinar un número generado por el servidor.

Código del Cliente (AdivinaCliente)

public class AdivinaCliente {
    public static final int PORT = 4444;
    public static void main(String[] args) {
        Socket socketCliente = null;
        BufferedReader entrada = null;
        PrintWriter salida = null;

        try {
            socketCliente = new Socket("127.0.0.1", PORT);
            entrada = new BufferedReader(new InputStreamReader(socketCliente.getInputStream()));
            salida = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socketCliente.getOutputStream())), true);
        } catch (ConnectException e) {
            System.err.println("¿Hay alguien al otro lado? No se pudo conectar con el servidor.");
            System.exit(-1);
        } catch (IOException e) {
            System.err.println("No se pudieron abrir los pipes de E/S.");
            System.exit(-2);
        }

        Scanner sc = new Scanner(System.in);
        String linea;

        try {
            System.out.print("Elige dificultad (facil, media, dificil): ");
            linea = sc.nextLine();

            if (!linea.equals("facil") && !linea.equals("media") && !linea.equals("dificil")) {
                System.out.println("No has introducido una dificultad válida.");
            } else {
                salida.println(linea);
                System.out.println("Vamos allá. Para rendirte escribe \"Rendirse\"");

                while (true) {
                    System.out.print("¿Qué número crees que es? ");
                    linea = sc.nextLine();

                    if (linea.equals("Rendirse")) {
                        salida.println("GIVEUP");
                        System.out.println("¡El número era " + entrada.readLine() + "!");
                        break;
                    }

                    try {
                        Integer.parseInt(linea);
                        salida.println(linea);
                        String resultado = entrada.readLine();
                        if (resultado.equals("GREATER")) {
                            System.out.println("No... es mayor.");
                        } else if (resultado.equals("LOWER")) {
                            System.out.println("No... es menor.");
                        } else if (resultado.equals("EQUAL")) {
                            System.out.println("¡Acertaste!");
                            break;
                        } else {
                            System.out.println("Respuesta inesperada del servidor: " + resultado);
                        }
                    } catch (NumberFormatException e) {
                        System.out.println("No has introducido un número válido.");
                    }
                }
            }
            salida.close();
            entrada.close();
            sc.close();
            socketCliente.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

Código del Servidor (AdivinaServidor)

public class AdivinaServidor {
    public static final int PORT = 4444;
    public static void main(String[] args) {
        ServerSocket socketServidor = null;
        try {
            socketServidor = new ServerSocket(PORT);
        } catch (IOException e) {
            System.out.println("No puede escuchar en el puerto: " + PORT);
            System.exit(-1);
        }

        Socket socketCliente = null;
        BufferedReader entrada = null;
        PrintWriter salida = null;

        try {
            socketCliente = socketServidor.accept();
            entrada = new BufferedReader(new InputStreamReader(socketCliente.getInputStream()));
            salida = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socketCliente.getOutputStream())), true);

            System.out.println("Servidor iniciado.");
            int max;
            switch (entrada.readLine()) {
                case "facil": max = 10; break;
                case "media": max = 100; break;
                default: max = 1000; break;
            }
            int numeroSecreto = new Random().nextInt(max + 1);
            System.out.println("Número secreto: " + numeroSecreto);

            String leido;
            while (true) {
                leido = entrada.readLine();
                if (leido.equals("GIVEUP")) {
                    salida.println(numeroSecreto);
                    break;
                }
                int numeroJugador = Integer.parseInt(leido);
                if (numeroSecreto > numeroJugador) {
                    salida.println("GREATER");
                } else if (numeroSecreto < numeroJugador) {
                    salida.println("LOWER");
                } else {
                    salida.println("acertado");
                    break;
                }
            }
            System.out.println("Servidor detenido");
            salida.close();
            entrada.close();
            socketCliente.close();
            socketServidor.close();
        } catch (IOException e) {
            System.out.println("IOException: " + e.getMessage());
        }
    }
}

2. Servidor Multihilo (Eco)

Para manejar múltiples clientes simultáneamente, utilizamos Threads (hilos).

Clase Worker (ClientWorker)

class ClientWorker extends Thread {
    Socket socketCliente;
    public ClientWorker(Socket socketCliente) {
        this.socketCliente = socketCliente;
    }

    @Override
    public void run() {
        BufferedReader entrada = null;
        PrintWriter salida = null;
        try {
            entrada = new BufferedReader(new InputStreamReader(socketCliente.getInputStream()));
            salida = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socketCliente.getOutputStream())), true);
            while (true) {
                String str = entrada.readLine();
                if (str == null) {
                    System.out.println("Cliente desconectado.");
                    break;
                }
                salida.println(str);
                if (str.equals("Fin")) break;
            }
            salida.close();
            entrada.close();
            socketCliente.close();
        } catch (IOException e) {
            System.out.println("No se pudieron abrir los streams de I/O para el cliente");
        }
    }
}

Servidor Principal (EcoServidorMultihilo)

public class EcoServidorMultihilo {
    public static final int PORT = 4444;
    public static void main(String[] args) throws IOException {
        ServerSocket socketServidor = new ServerSocket(PORT);
        while (true) {
            Socket socketCliente = socketServidor.accept();
            System.out.println("Cliente conectado: " + socketCliente);
            new ClientWorker(socketCliente).start();
        }
    }
}

3. Servidor Web Básico

Un ejemplo sencillo de cómo un servidor puede servir archivos estáticos mediante el protocolo HTTP.

public class ServidorWeb {
    public static final int PORT = 8080;
    public static void main(String[] args) throws IOException {
        ServerSocket socketServidor = new ServerSocket(PORT);
        while (true) {
            try (Socket socketCliente = socketServidor.accept()) {
                BufferedReader entrada = new BufferedReader(new InputStreamReader(socketCliente.getInputStream()));
                PrintWriter salida = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socketCliente.getOutputStream())), true);

                String str = entrada.readLine();
                if (str == null) continue;
                String[] partes = str.split(" ");
                String recurso = partes[1];
                File archivo = new File("." + recurso);

                if (archivo.exists() && !archivo.isDirectory()) {
                    byte[] contenidoBytes = Files.readAllBytes(archivo.toPath());
                    salida.println("HTTP/1.1 200 OK");
                    salida.println("Content-Type: text/html; charset=UTF-8");
                    salida.println("Content-Length: " + contenidoBytes.length);
                    salida.println();
                    Files.copy(archivo.toPath(), socketCliente.getOutputStream());
                } else {
                    salida.println("HTTP/1.1 404 Not Found");
                }
            } catch (IOException e) {
                System.out.println("IOException: " + e.getMessage());
            }
        }
    }
}

Entradas relacionadas: