使用RMI传递对象引用

时间:2011-09-10 00:47:03

标签: java rmi

大家好,

我一直在努力解决这个问题。如果有人能够看看我的问题并帮助我,我真的很感激。

我有多个客户端使用Java RMI建立连接(register())并从服务器接收连接客户端列表(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 { }
}

现在,创建客户端实例的Main类调用以下内容,将远程对象发送到服务器:

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

注册后,每个客户端都会请求连接用户列表。服务器中的功能如下:

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

如果Client也要实现Serializable,那么程序会运行但是当client2调用client1.message()时,会为client2调用message()方法并在此时抛出NullPointer。

我正在查看此链接:http://www.exampledepot.com/egs/java.rmi/args_Args.html,它给了我一个提示,它应该实现Remote而不是序列化以通过引用传递。我不确定为什么该计划在我的案件中抱怨。

我非常感谢我能得到的任何帮助。我一直试图解决这个问题一段时间,我似乎无法找到任何解决方案。

非常感谢!

2 个答案:

答案 0 :(得分:1)

你不能只通过RMI传递任意引用。客户端必须是Serializable,因此它将整个传递给目标,或者导出的远程对象本身,因此对它的远程引用会被传递并保持不变 - 即它是一个回调。

编辑:因为后者似乎是你的意图,所以你需要做的就是让客户扩展UnicastRemoteObject。

作为Oracle / Sun Java Tutorials的一部分,有一个优秀的RMI Trail。

答案 1 :(得分:1)

您需要导出客户端并将存根发送到服务器

编辑:这应该有效,它应该与导出服务器的方式相同(但不使用rmiregistry)

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