2016-08-14 2 views
-1

제 목표는 간단한 채팅 프로그램을 만드는 것입니다. 나는 RMI가 처음이다. 지금까지 내가 가진 것은 서버가 작동한다는 것입니다. 나는 그것을 시작한다. 그런 다음 클라이언트를 시작하고 RMI를 통해 문자열을 서버로 전송합니다. 그런데 내가 만든 GUI에는 나타나지 않습니다. 그것은 내 문제가있는 곳입니다.RMI를 사용하는 동안 GUI에 텍스트가 표시되지 않습니다.

My project structure

내 StartClient 클래스입니다. chatClient를 만들고 chatServer 스텁을 매개 변수로 지정합니다.

public StartClient() throws RemoteException, NotBoundException, MalformedURLException { 
    chatServer = (ChatServer) Naming.lookup("rmi://localhost:1099/chatServer"); 
} 

private void run() throws RemoteException, MalformedURLException, NotBoundException { 
    ChatClientImpl chatClient1 = new ChatClientImpl(chatServer, "ikke"); 
    new ChatFrame(chatClient1); 

    ChatClientImpl chatClient2 = new ChatClientImpl(chatServer, "bla"); 
    new ChatFrame(chatClient2); 
} 

public static void main(String[] args) throws RemoteException, NotBoundException, MalformedURLException { 
    StartClient start = new StartClient(); 
    start.run(); 
} 

원격 메서드 레지스터를 사용합니다.

public ChatClientImpl(ChatServer chatServer, String name) throws MalformedURLException, NotBoundException, RemoteException { 
    this.chatServer = chatServer; 
    this.name = name; 
    chatServer.register(this); 
} 

이제 우리는 REGISTER 메서드의 ChatServerImpl 클래스에 있습니다. 클라이언트의 ArrayList에 클라이언트를 추가합니다. 그런 다음 SENT 메소드를 사용하여 텍스트를 표시합니다. 각 클라이언트 객체에있는 RECEIVE 메소드를 호출합니다.

public class ChatServerImpl extends UnicastRemoteObject implements ChatServer { 
private List<ChatClient> clients; 

public ChatServerImpl() throws RemoteException { 
    this.clients = new ArrayList<ChatClient>(); 
} 

public void register(ChatClientImpl client) throws RemoteException { 
    clients.add(client); 
    send("server", client.getName() + " has entered the room"); 
} 

public void unregister(ChatClientImpl client) throws RemoteException { 
    clients.remove(client); 
    send("server", client.getName() + " has left the room"); 
} 

public void send(String name, String message) throws RemoteException { 
    for(ChatClient client : clients) { 
     client.receive(name + ": " + message); 
    } 
} 
} 

이것은 잘못된 것입니다. textReceiver는 항상 null입니다. (textReceiver이 속성은 클라이언트 객체의/필드입니다.)

public void receive(String message) { 
    if (textReceiver == null) return; 
    textReceiver.receive(message); 
} 

고객의 ArrayList를 자신의 textReceivers가 null에 설정되어이 모두 서버 측과 모든 클라이언트이다. StartClient를 돌아 보면 중요한 라인이 있습니다. 새 ChatFrame (chatClient)입니다. ChatFrame의 생성자에서 textReceiver를 설정합니다. 내가 RMI를 사용하지 않는 경우

public ChatFrame(ChatClientImpl chatClient) { 
    this.chatClient = chatClient; 
    chatClient.setTextReceiver(this); 
    String name = chatClient.getName(); 
    setTitle("Chat: " + name); 
    createComponents(name); 
    layoutComponents(); 
    addListeners(); 
    setSize(300, 300); 
    setVisible(true); 
} 

이 프로젝트

작동하고 하나 개의 패키지에있어하지만 난 클라이언트 - 서버로 분리하면이 문제가 발생했다. 어떻게 그들 사이에서 의사 소통을합니까? 서버 측 텍스트가 도착하더라도 영향을주지 않는 ChatClients 목록이 있습니다.

별도의 모든 ChatClient에 대해 RMI를 사용하고 ChatServer를 연결하여 그 텍스트를 보내시겠습니까? 나에게 매우 복잡해 보입니다. 어떻게해야합니까?

편집 :

ChatClientImpl 클래스

public class ChatClientImpl implements ChatClient, Serializable { 
private ChatServer chatServer; 
private TextReceiver textReceiver; 
private String name; 

public ChatClientImpl(ChatServer chatServer, String name) throws MalformedURLException, NotBoundException, RemoteException { 
    this.chatServer = chatServer; 
    this.name = name; 
    chatServer.register(this); 
} 

public String getName() { 
    return name; 
} 

public void send(String message) throws RemoteException { 
    chatServer.send(name, message); 
} 

public void receive(String message) { 
    if (textReceiver == null) return; 
    textReceiver.receive(message); 
} 

public void setTextReceiver(TextReceiver textReceiver) { 
    this.textReceiver = textReceiver; 
} 

public void unregister() throws RemoteException { 
    chatServer.unregister(this); 
} 
} 
+0

'ChatClientImpl'은 내 보낸 원격 객체입니까?그게 어디서 일어난거야? 'setTextReceiver()'는 어떻게 생겼는가? – EJP

+0

setTextReceiver()는 표준 설정 도구입니다. 내 원래 게시물에서 ChatClientImpl 클래스를 편집했습니다. "내 보낸 원격 객체"를 사용하면 클래스가 UnicastRemoteObject를 확장했는지 여부를 알 수 있습니까? 아니, 그 일을하려고했지만 chatServer.register (this)에 대한 IllegalArgumentException을 제공합니다. – Phosphophyllite

답변

0

귀하의 ChatClientImpl 클래스가 아닌 수출 원격 객체, 그것은 서버에 연재, 거기 실행할 수 있도록. 구성 중에 register()이 발생하기 때문에 setReceiverTextReceiver() 메서드가 호출되기 전에 serialize됩니다. 따라서 해당 필드는 null입니다. 서버에서. 이것은 당신이 원하는 것이 아니며 원하는 곳이 아닙니다.

그래서 으로 변경하고 UnicastRemoteObject으로 확장하고 ChatClient (예상되는) 원격 인터페이스를 구현하십시오. 그렇게하는 데 문제가 있다면 해결하십시오. 임의로 물건을 뒤적 거리지 마십시오. 그리고 이 아니며 Serializable을 구현해야합니다.

NB register()의 서명은 register(ChatClient client)이어야합니다. ChatClientImpl 클래스와 아무 관련이 없습니다. 위도 : unregister()

+0

도움에 감사드립니다. 나는 서명을 변경했다 (& ChatClientImpl 확장은'UnicastRemoteObject'를 확장했다.). 그리고 그것은 작동합니다. 제대로 이해가된다면 'ChatClientImpl'이 서버의 일반 객체이기 때문에 가능하지만 일단 URO로 확장하면 내 보낸 원격 객체가되고 서버는 클라이언트 측에 프레임과 원격으로 연결할 수 있습니다. (맞았 어?) 왜 내가 그 이전의'IllegalArgumentException'을 얻었 을까? RMI는 내 보낸 원격 객체 매개 변수 대신 원격 인터페이스 매개 변수에서만 작동합니다. 다시 한 번 감사드립니다! – Phosphophyllite

+0

수정. 'IllegalArgumentException'은 부정확 한 서명이나 객체 코드 버전 간의 불일치와 관련이 있습니다. 내 보낸 원격 객체는 원격 객체의 인스턴스가 아닌 원격 인터페이스를 구현하는 곳, 즉 스텁과 그 스텁에만 전송되지 않습니다. – EJP

관련 문제