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

在ChatClientImpl構造我使用遠程方法寄存器。

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始終爲空。 (textReceiver是屬性的客戶對象/場)。

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

客戶的ArrayList的是服務器端和所有客戶端在那裏都對空集的textReceivers。如果你回頭看看StartClient,有一條重要的路線。新的ChatFrame(聊天客戶端)。在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,他們是在一個封裝內,但一旦我把它們分爲客戶端服務器這種問題的出現。我如何在他們之間進行溝通?服務器端我有一個(無關緊要的)ChatClient列表,即使文本到達也不會影響任何內容。

我是否對每個單獨的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()是一個標準的setter。我在原始文章中編輯了ChatClientImpl類。使用「導出的遠程對象」,是否該類擴展了UnicastRemoteObject?不,我試過這樣做,但它爲chatServer.register(this)提供了IllegalArgumentException。 – Phosphophyllite

回答

0

ChatClientImpl類不是一個導出的遠程對象,所以它會被序列化到服務器,並執行那裏。並且因爲register()在施工期間發生,所以在調用setReceiverTextReceiver()方法之前將會被序列化。所以,相應的字段將爲空。在服務器上。這不是你想要的,也不是你想要的地方。

因此,使它延伸UnicastRemoteObject並實現您的ChatClient(推測)遠程接口。如果您遇到問題,請解決。不要隨意亂用東西。它應該而不是實施Serializable

NB register()的簽名應該是register(ChatClient client)。與ChatClientImpl類無關。同上unregister()

+0

感謝您的幫助。我改變了簽名(&製作了'ChatClientImpl'擴展'UnicastRemoteObject')。它的工作原理。如果我理解正確,這是因爲'ChatClientImpl'是服務器上的常規對象,但是一旦我用URO擴展它,它就成爲一個導出的遠程對象,並且服務器可以通過其框架遠程聯繫客戶端。 (對了嗎?)爲什麼我得到早期的'IllegalArgumentException'? RMI僅適用於遠程接口參數,而不是導出的遠程對象參數?再次謝謝你! – Phosphophyllite

+0

正確。 「IllegalArgumentException」與不正確的簽名或對象代碼版本之間的分歧有關。一個導出的遠程對象永遠不會傳輸到任何地方,只有它的存根,它的存根實現遠程接口,而不是當然是遠程對象的一個​​實例,即遠程接口的用途。 – EJP