Comunicación entre un servidor y múltiples clientes

Creación de un servidor en Java que soporte varios clientes al mismo tiempo con el uso de threads

Hoy veremos cómo hacer lo mismo pero dando soporte a muchos clientes al mismo tiempo utilizando para cada uno de ellos un Thread.

La estructura cliente-servidor es bastante similar, sin embargo, introducimos el concepto de Receptor. Para cada cliente que se conecte al servidor crearemos un nuevo hilo en el mismo que se encargará de gestionar el cliente.

Este receptor lo representamos con la clase Java: ServidorHilo.java

import java.io.*;
import java.net.*;
import java.util.logging.*;

public class ServidorHilo extends Thread {

    private Socket socket;
    private DataOutputStream dos;
    private DataInputStream dis;
    private int idSessio;

    public ServidorHilo(Socket socket, int id) {
        this.socket = socket;
        this.idSessio = id;
        try {
            dos = new DataOutputStream(socket.getOutputStream());
            dis = new DataInputStream(socket.getInputStream());
        } catch (IOException ex) {
            Logger.getLogger(ServidorHilo.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void desconnectar() {
        try {
            socket.close();
        } catch (IOException ex) {
            Logger.getLogger(ServidorHilo.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void run() {
        String accion = "";
        try {
            accion = dis.readUTF();
            if(accion.equals("hola")){
                System.out.println("El cliente con idSesion "+this.idSessio+" saluda");
                dos.writeUTF("adios");
            }

        } catch (IOException ex) {
            Logger.getLogger(ServidorHilo.class.getName()).log(Level.SEVERE, null, ex);
        }

        desconnectar();
    }
}

En el constructor creamos dos buffers (uno de entrada y otro de salida) para gestionar los envíos y recibos del cliente, y dentro del método RUN gestionamos qué hacer cuando recibamos un mensaje del cliente.

Servidor

La clase Servidor.java se encarga de asignar un nuevo Thread a cada nueva conexión.

import java.io.*;
import java.net.*;
import java.util.logging.*;

public class Servidor {

    public static void main(String args[]) throws IOException {

        ServerSocket ss;
        System.out.print("Inicializando servidor... ");
        try {
            ss = new ServerSocket(10578);
            System.out.println("\\t[OK]");
            int idSession = 0;
            while (true) {
                Socket socket;
                socket = ss.accept();
                System.out.println("Nueva conexión entrante: "+socket);
                ((ServidorHilo) new ServidorHilo(socket, idSession)).start();
                idSession++;
            }

        } catch (IOException ex) {
            Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

Cliente

El Cliente.java lo representamos mediante otra clase llamada Persona que se encarga de enviar y recibir los mesnajes que vienen y van del servidor.

import java.io.*;
import java.net.Socket;
import java.util.*;
import java.util.logging.*;

class Persona extends Thread {

    protected Socket sk;
    protected DataOutputStream dos;
    protected DataInputStream dis;
    private int id;

    public Persona(int id) {
        this.id = id;
    }

    @Override
    public void run() {
        try {
            sk = new Socket("127.0.0.1", 10578);
            dos = new DataOutputStream(sk.getOutputStream());
            dis = new DataInputStream(sk.getInputStream());

            System.out.println(id + " envía saludo");
            dos.writeUTF("hola");
            String respuesta="";
            respuesta = dis.readUTF();
            System.out.println(id + " Servidor devuelve saludo: " + respuesta);
            dis.close();
            dos.close();
            sk.close();
        } catch (IOException ex) {
            Logger.getLogger(Persona.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

public class Cliente {

    public static void main(String[] args) {
        ArrayList clients = new ArrayList();
        for (int i = 0; i < 5; i++) {
            clients.add(new Persona(i));
        }
        for (Thread thread : clients) {
            thread.start();
        }
    }

}

Como ejemplo, se crean 5 clientes que se conectan al servidor.