2017-09-23 7 views
1

자바에서 rmi와 채팅하고 있습니다. 하나의 서버 개체와 적어도 두 개의 클라이언트 개체가 있습니다. 클라이언트가 메서드 recebeMensagem을 원격으로 호출하는 서버에 메시지를 보내면 서버는 모든 클라이언트의 화면 (메시지를 보낸 클라이언트 제외)에서 해당 메시지를 인쇄해야합니다.Java RMI : 클라이언트 스텁 메소드를 클라이언트 화면의 서버 프린트 메시지에서 호출하는 방법은 무엇입니까?

클라이언트 클래스에는 서버에 의해 원격으로 호출되는 printMenssagem(Mensagem msg) 메서드가 있습니다. 문제는 해당 메서드가 서버의 화면에 인쇄하고 있다는 것입니다. 대신 클라이언트 화면에 메시지를 인쇄하려면 어떻게해야합니까?

Server.java :

import java.rmi.NotBoundException; 
import java.rmi.RemoteException; 
import java.rmi.registry.LocateRegistry; 
import java.rmi.registry.Registry; 
import java.rmi.server.UnicastRemoteObject; 
import java.util.ArrayList; 
import java.util.function.Predicate; 

public class Server implements ChatServer { 

    private ArrayList<String> listaClientes = new ArrayList<>(); 
    private static int port = 5002; 

    public static void main(String[] args) { 

     try { 

      Server obj = new Server(); 
      ChatServer stub = (ChatServer) 
      UnicastRemoteObject.exportObject(obj, port); 

      // Bind the remote object's stub in the registry 
      Registry registry = LocateRegistry.createRegistry(port); 
      registry.bind("chat", stub); 
      System.out.println("Server ready!"); 

     } catch (Exception e) { 
      System.err.println("Server exception: " + e.toString()); 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public void adicionaCliente(String user) { 

     this.listaClientes.add(user); 

    } 

    @Override 
    public void retiraCliente(String userName) { 
     Predicate<String> clientePredicate = cp -> 
     cp.equals(userName); 
     listaClientes.removeIf(clientePredicate); 
     try { 
      Registry registry = LocateRegistry.getRegistry(port); 
      registry.unbind(userName); 
     } catch (RemoteException e) { 
      e.printStackTrace(); 
     } catch (NotBoundException e) { 
      e.printStackTrace(); 
     } 

    } 

    @Override 
    public void recebeMensagem(Mensagem msg) {  

     try { 
      Registry registry = LocateRegistry.getRegistry(port); 
      for(String cliente : listaClientes) { 
       if (!cliente.equals(msg.getRemetente())) { 
        Client stub = (Client) registry.lookup(cliente); 
        stub.printMensagem(msg); 
       }      
      } 
     } catch (RemoteException e) { 
     e.printStackTrace(); 
    } catch (NotBoundException e) { 
     e.printStackTrace(); 
    } 

    } 


    public ArrayList<String> getListaClientes() { 
     return listaClientes; 
    } 

    public void setListaClientes(ArrayList<String> listaClientes) { 
     this.listaClientes = listaClientes; 
    } 



    } 

Client.java :

import java.io.Serializable; 
import java.rmi.Remote; 

public class Client implements Remote, Serializable { 

    private static final long serialVersionUID = 6864579049922061838L; 
    private static int port = 5002; 
    private static String host = "127.0.0.1"; 

    public static void main(String[] args) {   

     new Thread(new ClientInterface(host, port)).start();    
    } 


    public void printMensagem(Mensagem mensagem) { 
     System.out.println(mensagem.getRemetente() + ": " + mensagem.getMensagem()); 
    } 



} 

답변

1

방법 클라이언트 화면에서 서버 인쇄 메시지 호출 클라이언트 스텁 방법을 할?

클라이언트에 스텁이 없습니다. 그것은 원격 객체가 아닙니다. 이것은 직렬화 가능한 객체이며 레지스트리 holus bolus로 전송되었으며, JVM이 Registry.lookup()을 수행 한 모든 것을 실행하여 실행합니다. 이것은 당신이 원하는 것이 아닙니다. 스텁을 사용하여 원격 객체로 만들고 싶기 때문에 원격 인터페이스를 구현하고 내보내고 피어의 원격 인터페이스를 통해 사용해야합니다.

원격 레지스트리에 바인딩 할 수 없으므로 현재 아키텍처가 두 개 이상의 호스트에서 작동하지 않는다는 점도 알아야합니다. 서버에 클라이언트 등록 방법을 추가해야합니다.