Pilot Alpal Pilot Alpal - 6 months ago 10
Java Question

Multithread file server java

I´m implementig a concurrent file server in Java.

Each client has its own comunication chanel with the server. The server runs a thread for listening all conection requests,and another thread for listening and answering each connection. Each client runs a thread for comunication with de server and an other one for listening server petitions(files demanded by other clients).

Client

public class Cliente {
private static String nombre;
private InetAddress ip;
private static Socket s;
private static BufferedReader tCliente;
private static PrintWriter fCliente;
private static Usuario usr;
private static String idCliente;

public Cliente(){

}

public static void main(String args[]){
Cliente c=new Cliente();
Scanner teclado=new Scanner(System.in);
System.out.println("What´s your name?");
nombre=teclado.nextLine();
//construir cliente
try {
s= new Socket("ACER", 999);//¿Cómo obtengo la ip del Servidor? 192.168.1.101
tCliente=new BufferedReader(new InputStreamReader(s.getInputStream()));
fCliente=new PrintWriter(s.getOutputStream());
MensajeConexion mConexion=
new MensajeConexion(InetAddress.getLocalHost().getHostName(), "ACER",nombre);
fCliente.println(nombre);*/
(new OyenteServidor(s,c)).start();

while (true){
System.out.println("Que deseas hacer?");
System.out.println("1) Mostrar lista usuarios");
System.out.println("2) Pedir fichero");
System.out.println("3) Cerrar conexión");
int op = teclado.nextInt();
switch (op) {
case 1:
break;
case 2:
System.out.println("Que fichero quieres?");
String nombreFichero = teclado.nextLine();
break;
case 3:
s.close();
break ;
default:
System.err.println("Opción inválida");
break;
}
}
}
catch (IOException e) {

e.printStackTrace();
}


teclado.close();
}
public void print(String string) {
System.out.println(string);
}
}


Server

public class Servidor {
private static InetAddress ipServer;
private static final int portServer=999;
private static ServerSocket listen;
private static BufferedReader fServer;
private static PrintWriter tServer;
private static Socket s;
private static Hashtable<String, Usuario> tUsuarios;
private static Hashtable<String, ObjectOutputStream> tCanales ;


public Servidor(){

}
public static void main(String args[]){
Servidor ser=new Servidor();
try {
listen=new ServerSocket(portServer);
ipServer=listen.getInetAddress();
while(true){
s=listen.accept();
(new OyenteCliente(s,ser)).start();
}
}
catch (IOException e) {
e.printStackTrace();
}
}

public InetAddress getInetAdress(){
return ipServer;
}

public synchronized void guardaFlujo(Usuario usr, ObjectOutputStream fOut) {
tCanales.put(usr.getName(), fOut);

}
public synchronized void registra(Usuario usr) {
tUsuarios.put(usr.getName(), usr);
}
}


Threads for listening every client in server are implement in a class named OyenteCliente(ClientListener), and the thread that in every client listens server petitios is implemented in OyenteServidor(ServerListener).

ClientListener

public class OyenteCliente extends Thread {
private Servidor servidor;
private Socket s; private ObjectInputStream fIn;
private ObjectOutputStream fOut;
private Usuario infoCliente;
public OyenteCliente(Socket so,Servidor ser) {
servidor=ser;
s=so;
try {
fIn=new ObjectInputStream(s.getInputStream());//<---Server thread stops here
fOut=new ObjectOutputStream(s.getOutputStream());
}
catch (IOException e) {
e.printStackTrace();
}
}


@Override
public void run() {
while (true){
try {
Mensaje m= (Mensaje) fIn.readObject();
TipoMensaje type = m.getTipo();
switch (type) {
case Conexion:
Usuario usr= new Usuario(((MensajeConexion) m).getUserName());
servidor.registra(usr);
servidor.guardaFlujo(usr,fOut);
MensajeConfirmacion confirmacion = new MensajeConfirmacion(m.getDestino(),m.getOrigen());
fOut.writeObject(confirmacion);
break;
case ListaUsuarios:
/*
* -buscar info en tUsuarios
* -mandar msge conf lista usuarios
* */
break;
case EmitirFichero:
/*
* -obtener info usuario que tiene fichero
* -mandar mensaje peticion fichero
*
* */
break;
case PrepComCS:
/*
* mandar mensaje preparar comunicacion SC
* */
break;
default:
System.err.println(m);
break;
}
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}


ServerListener

public class OyenteServidor extends Thread{
private Socket myS;
private ObjectInputStream fIn;
private ObjectOutputStream fOut;
private Cliente client;

public OyenteServidor(Socket s,Cliente clie) {
client=clie;
try {
myS=s;
fIn=new ObjectInputStream(myS.getInputStream());//<---Client thread stops here
fOut=new ObjectOutputStream(myS.getOutputStream());
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run(){
while (true){
try {
Mensaje m = (Mensaje) fIn.readObject();
TipoMensaje type=m.getTipo();
switch (type) {
case ConfConexion:
client.print("Conexión confirmada");
break;
case ConfListaUsuarios:
break;
case PetFichero:
break;
case PrepComCS:
break;
default:
break;
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


I have to implement comunication by passing messages("ConectionRequest","FileRequest"..) so when I create every Socket I try to use a ObjectInputStream and a ObjectOutputStream in each listener to do so.

Debugging (Cliente and Servidor) I´ve just found out that both proceses pauses for ever when they initialize their ObjectInputStream with Socket.getInputStream().

Could anyone tell how wrong am I?

Thank you very much!

EJP EJP
Answer

You need to construct the ObjectOutputStream before the ObjectInputStream.

You also need to construct the same streams at both ends. Your present mixture of streams will not work.

You also need to remove the keyword static throughout, if you expect this to work with multiple threads.

Comments