【问题标题】:Java RMI:Updating client side objects in the serverJava RMI:更新服务器中的客户端对象
【发布时间】:2013-12-20 12:45:42
【问题描述】:

我正在尝试使用 Java RMI 在分布式系统中实现用于组通信的中间件。

在那里,我需要向服务器发送一个对象并对其进行修改。因此,更改应该反映在客户端。

例如,我将给出Oracle网站上最常见的教程:

X.java

public class X  implements Serializable, Remote{
    public int x; // defined as public, just be simple.
}

Hello.java

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Hello extends Remote {

    String sayHello(X c) throws RemoteException;
}

服务器.java

import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;

public class Server implements Hello {

    public Server() {
    }

    public String sayHello(X c) {
        c.x = 10;
        return "Hello, world!";
    }

    public static void main(String args[]) {

        try {
            Server obj = new Server();
            Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0);
            LocateRegistry.createRegistry(1099);
            // Bind the remote object's stub in the registry
            Registry registry = LocateRegistry.getRegistry();
            registry.bind("Hello", stub);

            System.err.println("Server ready");
        } catch (Exception e) {
            System.err.println("Server exception: " + e.toString());
            e.printStackTrace();
        }
    }
}

客户端.java

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class Client {

    public int x = 4;

    private Client() {
    }

    public static void main(String[] args) {

        String host = (args.length < 1) ? null : args[0];
        try {
            Registry registry = LocateRegistry.getRegistry(host);
            Hello stub = (Hello) registry.lookup("Hello");
            X x = new X();
            String response = stub.sayHello(x);
            System.out.println("response: " + x.x);
        } catch (Exception e) {
            System.err.println("Client exception: " + e.toString());
            e.printStackTrace();
        }
    }
}

我的问题是,即使我在服务器端的对象 c 中更新 x 的值,它也不会反映到客户端。我可以简单地使用return 来获取更新的值,但我打算使用这种方法来实现服务器的多播功能。

谁能解释为什么?如果我需要这样做,该怎么做?

【问题讨论】:

    标签: java rmi remote-access


    【解决方案1】:

    当您使用 RMI 时,您有 2 个(或更多)java 虚拟机参与给定的计算,因此当您在客户端创建对象并调用服务器上的方法时,将该对象作为参数传递给状态对象的序列化并通过网络发送。在服务器端,创建同一个类的新对象并在其上设置状态,但它是具有相同值的不同对象。对此克隆进行操作不会反映仍驻留在源虚拟机上的原始对象。

    您可以在运行虚拟机的每台机器上使用 rmiregistry 并注册每个对象以公开它(这是一个分布式解决方案),或者您可以将所有数据对象集中在具有 rmiregistry 的机器上(这是一个集中式解决方案,因为所有对象都在同一台机器上)。

    干杯!

    【讨论】:

    • 您不需要在每个虚拟机上,甚至在每个主机上都需要一个注册表。整个 RMI 系统中只需要一个注册表,有时甚至不需要。
    • @EJP 如果仔细阅读我的回答,您会发现我建议可以使用注册表来创建分发基础架构。
    • 如果您自己仔细阅读您的答案,您会发现您说过“您必须...?”这是不正确的。你没有。您最多需要一个注册表。客户端可以通过 RMI 直接向服务器注册他们的回调。
    • @EJP 我正在阅读我的作品,现在在我看来,我当时的写作方式听起来很粗鲁。你写的是我所说的。我会花时间在答案中说清楚。
    • 但您实际上从未这样做过。
    【解决方案2】:

    RMI 并不神奇。它是远程方法调用。您必须调用远程方法才能在远程位置发生某些事情。仅仅改变一个变量并让它通过网络神奇地传播并不在 RMI 的范围内。

    无论您想远程发生什么,都必须由远程接口中的方法定义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-09
      • 2010-12-31
      • 1970-01-01
      • 1970-01-01
      • 2017-10-26
      相关资源
      最近更新 更多