Problema Java aplicación cliente/servidor multihilo acceso concurrente

Iniciado por Pantera80, 3 Febrero 2014, 09:10 AM

0 Miembros y 1 Visitante están viendo este tema.

Pantera80

Hola a todos. Soy nuevo por este foro, pero parece bastante interesante.

Bueno, el tema es que estoy realizando un trabajo de una aplicación cliente/servidor multihilo donde se espera que el servidor que programo acepte accesos concurrentes.
Trata de una especie de banco con sus cuentas, donde tengo sincronizados los métodos para actualizar esas cuentas.

El problema me surge cuando lanzo más de una instancia del cliente simultáneamente, ya que la última instancia me funciona, pero las anteriores se bloquean. Por consola el servidor me indica : error java.net.Socket socket closed.

He probado de todo pero no doy con la solución. Os adjunto el código por si alguien puede hacer algo. Muchas gracias de antemano.




Servidor.java


import java.io.*;
import java.net.*;




class Servidor extends Thread {


    private int estado;
    Socket skCliente;
    static final int Puerto = 8888;
    private int NumCuenta;
    private double Cantidad;
    public static DataInputStream flujo_entrada;
    public static DataOutputStream flujo_salida;
    String menu = "Seleccionar una opción: \n"
                + "[1] Ingresar una cantidad \n"
                + "[2] Reintegrar una cantidad \n"
                + "[3] Consultar el saldo \n"
                + "[0] Salir \n"
                + "Escriba su elección :";
    //Esta constante nos va a permitir indicar al cliente cuándo debe escribir
    final String control = "escribir";
    public static RecursoServidor recursoServidor;

   
    public Servidor(Socket sCliente) {
        skCliente = sCliente;
                     
    }

    public static void main(String[] arg) {

         recursoServidor = new RecursoServidor();
       
        try {
            // Inicio el servidor en el puerto
            ServerSocket skServidor = new ServerSocket(Puerto);
            System.out.println("Escucho el puerto " + Puerto);

             
            while (true) {
                // Se conecta un cliente
                Socket skCliente2 = skServidor.accept();
                System.out.println("Cliente conectado");
                // Atiendo al cliente mediante un thread
                new Servidor(skCliente2).start();
               
            }
        } catch (Exception e) {
            System.out.println("Error al conectar un cliente"+e.getStackTrace());
        }
    }








   
    @Override
    public  void  run() {
        try {
            // Creo los flujos de entrada y salida
            flujo_entrada = new DataInputStream(
                    new BufferedInputStream(skCliente.getInputStream()));
            flujo_salida =  new DataOutputStream(
                    new BufferedOutputStream(skCliente.getOutputStream()));
           
            // ATENDER PETICIÓN DEL CLIENTE
            flujo_salida.writeUTF("Se ha conectado el cliente de manera correcta");
            flujo_salida.flush();
           
            estado = 0;
            String comando="";

            flujo_salida.writeUTF("Menú de acceso a la Cuenta "
                                    + "Bancaria \n"
                                    + "Introduzca Número de Cuenta [0-9]:");
            flujo_salida.flush();

            flujo_salida.writeUTF(control);
            flujo_salida.flush();

            NumCuenta =Integer.parseInt(flujo_entrada.readUTF());

                do {
                    switch (estado) {

                        case 0:
                           
                            flujo_salida.writeUTF(menu);
                            flujo_salida.flush();
                            flujo_salida.writeUTF(control);
                            flujo_salida.flush();
                            comando = flujo_entrada.readUTF();
                           
                           
                            if (comando.equals("1")) {
                               //Vamos al estado 1, realizar un ingreso
                                estado = 1;
                                break;
                            } else if (comando.equals("2")) {
                                // Vamos al estado 2, realizar un reintegro
                                estado = 2;
                                break;
                            } else if(comando.equals("3")){
                                //Vamos al estado 3, consultar el saldo
                                estado = 3;
                                break;
                            }else if(comando.equals("0")){
                                //Vamos al estado 4, salir
                                estado=4;
                                break;
                            }
                            break;

                        case 1:
                            flujo_salida.writeUTF("Realización de un Ingreso ");
                            flujo_salida.writeUTF("Cantidad que desea ingresar: ");
                            flujo_salida.flush();
                            flujo_salida.writeUTF(control);
                            flujo_salida.flush();
                           
                            Cantidad = Double.valueOf(flujo_entrada.readUTF());
                           
                            new IngresaCuenta(NumCuenta,Cantidad,recursoServidor).start();
                           
                            //Volvemos al estado 0, el inicio
                            estado=0;
                           
                            break;

                        case 2:
                            flujo_salida.writeUTF("Realización de un Reintegro ");
                            flujo_salida.writeUTF("Cantidad que desea reintegrar: ");
                            flujo_salida.flush();
                            flujo_salida.writeUTF(control);
                            flujo_salida.flush();
                            Cantidad = Double.valueOf(flujo_entrada.readUTF());
                           

                            new ReintegraCuenta(NumCuenta,Cantidad,recursoServidor).start();

                            //Volvemos al estado 0, el inicio
                            estado=0;
                            break;
                        case 3:
                            flujo_salida.writeUTF("Consulta de Saldo \n");
                            flujo_salida.flush();
                           
                            //Consultamos la cantidad al número de cuenta correspondiente
                            Cantidad = recursoServidor.consultarSaldo(NumCuenta);
                           
                            flujo_salida.writeUTF("Recibiendo: El saldo de la cuenta"
                                    + " es : "+String.valueOf(Cantidad));
                            flujo_salida.flush();
                           
                            //Volvemos al estado 0, el inicio
                            estado=0;
                            break;
                    }

                    if (comando.equals("0")) {
                        estado = 4;
                    }
                } while (estado != 4);

           
            // Se cierra la conexión
            flujo_salida.writeUTF("Cliente desconectado");
            flujo_salida.flush();
           
            skCliente.close();
            System.out.println("Cliente desconectado \n");
           
        } catch (Exception e) {
            System.out.println("Error :"+e.toString());
        }
    }
   
}


Cliente.java


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

class Cliente {

    static final String HOST = "localhost";
    static final int Puerto = 8888;
    //Esta constante nos va a permitir indicar al cliente cuándo debe escribir
    final String control="escribir";

       
   
    public Cliente() {
        try {
           Socket sCliente = new Socket(HOST, Puerto);
            // Creo los flujos de entrada y salida
            DataInputStream flujo_entrada = new DataInputStream(
                    new BufferedInputStream(sCliente.getInputStream()));
            DataOutputStream flujo_salida = new DataOutputStream(
                    new BufferedOutputStream(sCliente.getOutputStream()));

           
            String datosEntrada="", datosSalida="";
            //Se crea el objeto scanner que leera la entrada del sistema
            Scanner sc = new Scanner(System.in);



            //Ejecutaremos este bucle hasta que el servidor nos indique que
            //estamos desconectados
            do {
                // procesar mensajes enviados del servidor
                datosEntrada = flujo_entrada.readUTF();

               
                //Si no es el mensaje de control, se mostrará por consola
                if(!datosEntrada.equals(control)){
                        System.out.println(datosEntrada);

                }
                //Si recibimos el mensaje de control, el usuario debe escribir
                if(datosEntrada.equals(control)){
                    datosSalida=sc.nextLine();
                   
                    flujo_salida.writeUTF(datosSalida);
                    flujo_salida.flush();
                   
                }

            } while ( !datosEntrada.equals( "Cliente desconectado" ) );
             sCliente.close();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    public static void main(String[] arg) {
        new Cliente();
    }
}

Pantera80

Me contesto a mí mismo. Creo que ya he hallado el problema:

"Dentro de una red, un socket es único pues viene caracterizado por cinco parámetros: el protocolo usado (HTTP, FTP, etc.), dos direcciones IP (la del equipo local o donde reside el proceso cliente, y la del equipo remoto o donde reside el proceso servidor) y dos puertos (uno local y otro remoto) "

Al instanciar la clase Cliente varias veces desde mi mismo pc no creo sockets diferentes, ya que tienen todos la misma IP

O al menos eso creo