2011-09-10 73 views
2

大家好,傳遞使用RMI的對象引用

我一直在砸我的腦袋,努力解決這個問題。我真的很感激,如果有人可以請看看我的問題,並幫助我。

我有一個使用Java RMI建立連接多個客戶端(註冊()),並接收來自服務器的客戶端連接的列表(get()方法)。我的目標是讓客戶使用RMI相互交談,而不必註冊自己,只有服務器到目前爲止正在註冊。

我試圖通過客戶對象服務器的參考。

我收到以下錯誤:

java.rmi.MarshalException: error marshalling arguments; nested exception is: 
    java.io.NotSerializableException: Client 

我不想使用序列化(我認爲),因爲我不希望傳遞的對象本身,而是一個參考。 Client1應該能夠通過調用client2.messsage(String username,String message)向Client2發送消息;

我相信我應該在這一點告訴你如何我已經實現了我的代碼:

public interface RMIClientIntf extends Remote { 
    public void message(String name, String message) throws RemoteException; 
    public String getName() throws RemoteException; 
} 

前面的代碼是什麼,所有的客戶應該實施。如果從另一個客戶端調用message()函數,那意味着其他類正在發送消息。

我的客戶類本身:

public class Client implements RMIClientIntf { 
    public Client() throws RemoteException { super(); } 
    public String getName() throws RemoteException { } 
} 

現在,創建客戶端的一個實例調用下面的主類,遠程對象發送到服務器:

final Client client = new Client(); 
server.register((RMIClientIntf) client, name); 

在服務器側,註冊方法定義爲:

public interface RMIServerIntf extends Remote { 
    public String register(RMIClientIntf cl, String userName) throws RemoteException; 
    public RMIClientIntf[] get() throws RemoteException; 
} 


public class Server extends UnicastRemoteObject implements RMIServerIntf { 
    public String register(RMIClientIntf cl, String userName) throws RemoteException { 
     ClientStruct newClient = new ClientStruct(cl, userName); 
     /* Store the ClientStruct */ 
     return new String("SUCCESS"); 
    } 
} 

註冊後,每個客戶端將req請使用已連接的用戶列表。在服務器的功能如下:

public RMIClientIntf[] get() throws RemoteException { 
    RMIClientIntf[] users = new RMIClientIntf[openConnections.size()]; 
    /* Fill in users from ClientStruct */ 
    return users; 
} 

如果客戶端上,也能實現Serializable接口,那麼程序運行,但是當客戶機程序調用client1.message(),消息()方法被調用的客戶端2和拋出一個空指針在這一點上。

我看這個鏈接:http://www.exampledepot.com/egs/java.rmi/args_Args.html,這給了我一個提示,它應該實現遠程但不序列化按引用傳遞。我不確定該計劃爲什麼抱怨我的情況。

我真的很感謝任何幫助,我可以得到。我一直在試圖解決這個問題一段時間,我似乎無法找到任何解決方案。

非常感謝!

回答

1

您需要導出客戶端,並將存根服務器

編輯:這應該工作,應該導出服務器(但不使用rmiregistry中)

server.register((RMIClientIntf) UnicastRemoteObject.exportObject(client,0), name); 
+0

我不知道該怎麼做。你有教程嗎?我目前有Client.java文件部分的類路徑和服務器,客戶端和接口項目(其中包含Client.java代碼)的代碼庫。 – Jary

+0

@jary檢查編輯 –

+0

非常感謝!我得到它的工作。非常感謝你! – Jary

1

你不能只是通過任意的引用各地通過RMI。客戶端必須是要麼序列化的,所以它被傳遞到整個目標,或導出的遠程對象本身,這樣的遠程引用它被通過,它原地踏步 - 即它是一個回調。

編輯:因爲後者似乎是你的意圖,所有你需要的就是讓客戶端繼承UnicastRemoteObject。

作爲Oracle/Sun​​的一部分,有一個很好的RMI Trail。

+0

怎麼可能以同樣的方式我請自己製作一個導出的遠程對象?你有一個簡單的教程嗎? – Jary

+0

太棒了!我得到它的工作,非常感謝!代碼如下:\t \t \t RMIClientIntf stub =(RMIClientIntf)UnicastRemoteObject.exportObject(client,0); \t \t \t String response = server.register(stub,name); – Jary