【问题标题】:Passing object reference using RMI使用 RMI 传递对象引用
【发布时间】:2011-09-10 00:47:03
【问题描述】:

大家好,

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

我有多个使用 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,它给了我一个提示,它应该实现远程而不是序列化以通过引用传递。我不确定为什么程序会抱怨我的情况。

我非常感谢我能得到的任何帮助。我一直在尝试解决这个问题,但似乎找不到任何解决方案。

非常感谢!

【问题讨论】:

    标签: java rmi


    【解决方案1】:

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

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

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

    【讨论】:

    • 我不知道该怎么做。请问有教程吗?我目前拥有类路径的 Client.java 文件部分以及服务器、客户端和接口项目(包含 Client.java 代码)的代码库。
    • 代码 (a) 无法编译 (b) 没有意义, (c) 不是他导出服务器的方式。
    • @EJP 已修复(并且 exportObject 仅返回 Remote,而不是 RMIClientIntf)
    • 当我写那条评论时,你的代码没有调用 exportObject()。我不是读心术。
    【解决方案2】:

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

    编辑:因为后者似乎是您的意图,您需要做的就是让 Client 扩展 UnicastRemoteObject。

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

    【讨论】:

    • 我怎样才能自己制作一个导出的远程对象?请问有简单的教程吗?
    • 太棒了!我得到它的工作,非常感谢!代码如下: RMIClientIntf stub = (RMIClientIntf) UnicastRemoteObject.exportObject(client, 0);字符串响应 = server.register(stub, name);
    猜你喜欢
    • 2020-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-14
    • 2015-03-06
    • 2011-03-18
    相关资源
    最近更新 更多