[Java] Duda con conexiones de hilos en Java

Buenas, estoy haciendo una aplicación cliente/servidor en java y tengo una duda que no consigo solucionar.

La aplicación se basa en que un cliente puede ir enviándo mensajes(escribir) que se almacenan en un buffer o bien ir sacando los mensajes del buffer(leer)


¿Alguna sugerencia? El problema es como enviar el hilo que recibe hacia el hilo del servidor correspondiente y con el de leer lo mismo. [mad]

EDITO: Solucionado
minius escribió:La aplicación se basa en que un cliente puede ir enviándo mensajes(escribir) que se almacenan en un buffer o bien ir sacando los mensajes del buffer(leer)


No sé si lo he entendido bien:
- Hay un "buffer" en el server
- Se puedan conectar múltiples clientes (al mismo puerto, no hace falta crear un servidor en otro puerto por cada nuevo cliente)
- Cada cliente puede leer o escribir del buffer

Si es así, te recomiendo primero la lectura de:
http://docs.oracle.com/javase/tutorial/ ... erver.html

Mírate los ejemplos del final, la parte de múltiples clientes.

En tu caso, supongo que habría que añadir el buffer de forma "static" en la clase MultiServerThread, junto con el protocolo de leer y escribir.

Por curiosidad, ¿cuál es la clase Buffer que usas?
EXGeese escribió:
minius escribió:La aplicación se basa en que un cliente puede ir enviándo mensajes(escribir) que se almacenan en un buffer o bien ir sacando los mensajes del buffer(leer)


No sé si lo he entendido bien:
- Hay un "buffer" en el server
- Se puedan conectar múltiples clientes (al mismo puerto, no hace falta crear un servidor en otro puerto por cada nuevo cliente)
- Cada cliente puede leer o escribir del buffer

Si es así, te recomiendo primero la lectura de:
http://docs.oracle.com/javase/tutorial/ ... erver.html

Mírate los ejemplos del final, la parte de múltiples clientes.

En tu caso, supongo que habría que añadir el buffer de forma "static" en la clase MultiServerThread, junto con el protocolo de leer y escribir.

Por curiosidad, ¿cuál es la clase Buffer que usas?


La finalidad es tener comunicación asíncrona, es decir, un cliente puede estar escribiendo en el buffer sin que necesitemos tener otro leyendo o al revés.

La clase buffer es una propia que solamente tiene un array donde va acumulando los mensajes y dos métodos, uno para añadir al buffer y otro para sacar el mensaje del buffer.Estos dos métodos son synchronized para que no puedan juguetear con el buffer más de un hilo a la vez.

Lo de crear el servidor con hilos es para no bloquear la conexión cuando se conecten varios clientes, voy a modificarlo para que acepte las conexiones al mismo puerto pero entonces la duda que tengo es como puedo saber si el que se conecta es el cliente que quiere escribir o el que quiere leer.

Porque según sea un cliente u otro lo deribo al hilo del servidor correspondiente.Creo que está relacionado con la clase KnockKnockProtocol que me pasas en el ejemplo, voy a ponerme a mirarlo a fondo.
Vale, entendido.

Yo lo que había pensado es en poner un protocolo de manera que no haya un "cliente de lectura" o "cliente de escritura" si no que cualquiera que se conecte peuda decidir qué hacer de manera interactiva con el server.

Y en vez de una clase "Buffer" propia, usar una cola FIFO de manera que cada cliente pueda dejar su mensaje y también leer el mensaje más antiguo o pendiente de leer. Como la cola tiene una capacidad determinada, podría aumentarla dinámicamente o dejarla fija y bloqueante, de manera que hasta que un cliente no lee de la cola llena, los que quieren escribir permanecen a la espera.

Voy a poner mi propuesta basándome en el ejemplo de Oracle, y de paso practico con la etiqueta spoiler que no la he usado aún, por si no quieres verlo antes de pegarte tú con ello y para no scrollear mucho XD

La clase Cliente:
package sockets;

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

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

        Socket socket = null;
        PrintWriter out = null;
        BufferedReader in = null;

        try
        {
           socket = new Socket("localhost", 4444);
            out = new PrintWriter(socket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        }
        catch (UnknownHostException e)
        {
            System.err.println("Host desconocido: localhost.");
            System.exit(1);
        }
        catch (IOException e)
        {
            System.err.println("No se puede establecer conexión I/O con: localhost.");
            System.exit(1);
        }

        BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
        String fromServer;
        String fromUser;

        while ((fromServer = in.readLine()) != null)
        {
            System.out.println("Server: " + fromServer);
            if (fromServer.equals("ADIOS"))
                break;
             
            fromUser = stdIn.readLine();
            if (fromUser != null)
            {
                System.out.println("Client: " + fromUser);
                out.println(fromUser);
            }
        }

        out.close();
        in.close();
        stdIn.close();
        socket.close();
    }
}



La clase Multiserver:
package sockets;

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

public class MultiServer
{
    public static void main(String[] args) throws IOException
    {
       int portNumber = 4444;

        boolean listening = true;
       
        try (ServerSocket serverSocket = new ServerSocket(portNumber))
        {
            while (listening)
            {
               new MultiServerThread(serverSocket.accept()).start();
           }
       }
        catch (IOException e)
        {
            System.err.println("No se encuentra disponible el puerto " + portNumber);
            System.exit(-1);
        }
    }
}



La clase MultiServerThread:
package sockets;

import java.net.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.io.*;

public class MultiServerThread extends Thread
{
    private Socket socket = null;
   
    private static ArrayBlockingQueue<String> abq = new ArrayBlockingQueue<String>(5, true);

    public MultiServerThread(Socket socket)
    {
        super("KKMultiServerThread");
        this.socket = socket;
    }
   
    public void run()
    {

        try (
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(
                new InputStreamReader(
                    socket.getInputStream()));
        )
        {
           String inputLine, outputLine = "";
           
            out.println("HOLA");
           
            while ((inputLine = in.readLine()) != null)
            {
               if(inputLine.equalsIgnoreCase("LEER"))
               {
                  if (abq.size() > 0)
                  {
                     outputLine = abq.poll();
                  }
                  else
                  {
                     outputLine = "No hay mensajes";
                  }
               }
               else if( (inputLine.length() > 8) && (inputLine.substring(0,8).equalsIgnoreCase("ESCRIBIR")) )
               {
                  try
                  {
                   abq.put(inputLine.substring(9));
                   outputLine = "Ok, mensaje recibido";
                }
                  catch (InterruptedException e)
                {
                     outputLine = "Fallo, mensaje interrumpido";
                   e.printStackTrace();
                }
               }
               else if(inputLine.equalsIgnoreCase("SALIR"))
               {
                  outputLine = "ADIOS";
               }
               else
               {
                  outputLine = "Comando desconocido: " + inputLine;
               }
               
               out.println(outputLine);

            }
            socket.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}

3 respuestas