多线程文件服务器java

时间:2016-05-27 08:43:54

标签: java multithreading file sockets objectinputstream

我实现了Java中的并发文件服务器。

每个客户端都有自己的通信服务器。服务器运行一个线程来监听所有连接请求,另一个线程用于监听和回答每个连接。每个客户端运行一个线程用于与服务器通信,另一个用于监听服务器请求(其他客户端要求的文件)。

客户端

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);
   }
}

服务器

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);
}
}

用于侦听服务器中每个客户端的线程都在名为OyenteCliente(ClientListener)的类中实现,并且每个客户端侦听服务器petitios的线程都在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();
        }
    }
}

我必须通过传递消息来实现通信(“ConectionRequest”,“FileRequest”..)所以当我创建每个Socket时,我尝试在每个侦听器中使用ObjectInputStream和ObjectOutputStream来执行此操作。

调试(Cliente和Servidor)我刚刚发现,当他们使用Socket.getInputStream()初始化ObjectInputStream时,两个进程都会暂停。

有谁能告诉我有多错?

非常感谢!

3 个答案:

答案 0 :(得分:0)

您需要在body { background-color: #ffffcc; margin: 0; padding: 0; } header { height: 100px; width: 100%; background-color: #006600; overflow: auto; top: 0; position: fixed; } .img-circular { width: 70px; height: 70px; position: absolute; background-image: url(https://cdn0.iconfinder.com/data/icons/black-icon-social-media/256/099280-blinklist-logo.png); background-size: cover; border-radius: 50%; -webkit-border-radius: 50%; -moz-border-radius: 50%; left: 50%; margin: 15px 0 0 -35px; background-color: white; } .main { background-color: red; height: 1000px; }之前构建<!DOCTYPE html> <html lang="pl"> <html> <head> <meta charset="UTF-8" /> <meta name="description" content="Roto-car topowy szczeciński warsztat samochodowy"> <meta name="keywords" content="warsztat,szczecin,serwis,samochód,samochodowy,car,repair,fix,naprawa,samochodu,auto"> <meta name="author" content="Dominik Leszczenko"> <link rel="stylesheet" href="css/stylesheet.css" /> <title>Roto-car - Szczeciński warsztat samochodowy</title> </head> <body> <header> <div class="img-circular"></div> </header> <div class="main"> <h1>Roto-car</h1> <hr> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> </div> </body> </html>

您还需要在两端构建相同的流。你目前的溪流混合物将不起作用。

如果您希望这可以与多个线程一起使用,则还需要始终删除关键字ObjectOutputStream

答案 1 :(得分:0)

感谢您的回答。足以让我继续我的项目。 这就是我如何解决它。我可以为任何可能感兴趣的人分享我的解决方案,或者想要教给我任何其他东西。

ClientListener:

public class OyenteCliente extends Thread {
private Servidor servidor;
private Socket s;   
private ObjectInputStream fIn;
private ObjectOutputStream fOut;
public OyenteCliente(Socket so,Servidor ser) {
    servidor=ser;
    s=so;
    try {
        fOut=new ObjectOutputStream(s.getOutputStream());
        fIn=new ObjectInputStream(s.getInputStream());
    } 
    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());
                //-Guardar en tUsuarios info nuevo usuario
                servidor.registra(usr);
                /* -Guardar en tCanales flujo de comunicacion   * */
                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;
    myS=s;
    try {
        fOut=new ObjectOutputStream(myS.getOutputStream());
        fIn=new ObjectInputStream(myS.getInputStream());
        fOut.writeObject(new MensajeConexion(clie.getIp(), 
                myS.getInetAddress().getHostAddress(), client.getName()));
    } 
    catch (IOException e) {
        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) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 }
}

答案 2 :(得分:-1)

这是因为ObjectInputStream块的ctor。看看docs。也许你应该使用另一个像BufferedInputStream这样的输入流。