2016-08-14 11 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); 
} 

今、私たちはChatServerImplクラスのREGISTERメソッドに入っています。クライアントの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のは、サーバー側であり、そこではすべてのクライアントのすべてがnullに設定された彼らのtextReceiversを持っています。 StartClientを振り返ると、重要な行があります。新しいChatFrame(chatClient)。 ChatFrameのコンストラクタでは、私はtextReceiverを設定します。

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

このプロジェクトは、RMIを使用せず、1つのパッケージに含まれていますが、クライアントとサーバーに分かれてしまうと、この問題が発生しました。どうやってそれらの間でコミュニケーションを取るのですかサーバー側私は、テキストが到着しても何も影響を及ぼさないChatClientsのリスト(無関係なもの)を持っています。

別個のChatClientごとにRMIを使用して、ChatServerに接続してそのようなテキストを送信しますか?私にとっては非常に複雑に思えます。これについてどうすればいいですか?

EDIT:

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()メソッドが呼び出される前にシリアル化されます。したがって、対応するフィールドはnullになります。サーバーで。これはあなたが望むものではなく、あなたが望む場所でもありません。

ので、は、それがUnicastRemoteObjectを拡張し、あなたのChatClient(推定)リモートインタフェースを実装を作ります。それに問題がある場合は、解決してください。恣意的に物事を混乱させないでください。そしてでなく、Serializableを実装する必要があります。

NB register()の署名はregister(ChatClient client)である必要があります。 ChatClientImplクラスとは関係ありません。同上はunregister()です。

+0

助けてくれてありがとう。私は署名を変更しました(&ChatClientImpl拡張は 'UnicastRemoteObject'を拡張しました)。そして、それは動作します。私が正しく理解しているのは、 'ChatClientImpl'がサーバー上の通常のオブジェクトだったからです。しかし、UROで拡張した後は、エクスポートされたリモートオブジェクトとなり、サーバーはクライアントサイドにそのフレームでリモート接続できます。 (それが正しいのですか?)なぜ私は以前の 'IllegalArgumentException'を取得しましたか? RMIは、エクスポートされたリモートオブジェクトパラメータではなく、リモートインタフェースパラメータでのみ機能しますか?再びありがとう! – Phosphophyllite

+0

修正。 'IllegalArgumentException'は不正な署名やオブジェクトコードのバージョンの不一致と関係していました。エクスポートされたリモートオブジェクトは、リモートオブジェクトのインスタンスではなく、リモートインタフェースを実装するのではなく、どこでも、スタブだけ、およびスタブだけが転送されることはありません。 – EJP

関連する問題