【问题标题】:Make sure RMI only operates on one Server instance确保 RMI 仅在一个服务器实例上运行
【发布时间】:2014-02-22 22:06:19
【问题描述】:

我目前正在尝试通过实现服务器/客户端结构来掌握 RMI 的基础知识,其中客户端可以调用服务器上的远程操作,并且服务器可以调用客户端函数:

public class Client extends GenericRMI implements ClientInterface {
    public ServerInterface server;

    public Client() {
    try {
        String IP = InetAddress.getLocalHost().getHostAddress();

        server = (ServerInterface) Naming.lookup("//192.168.2.124/WServer");

        int uniqueID = (int) Math.round(Math.random() * 1000);

        super.setUpRMI("WClient" + IP + "_" + uniqueID);

        server.registerNewClient(IP, uniqueID);

    } catch (Exception e) {
        e.printStackTrace();
    }
    }

public void setUserID(int id) {
    System.out.println("got my ID from the server: " + id);
}
}

public class Server extends GenericRMI implements ServerInterface {
private List<ClientInterface> clients;

public Server() {
    clients = new ArrayList<ClientInterface>();
    super.setUpRMI("WServer");
}

public void registerNewClient(String IP, int uID) throws RemoteException {
    try {
        ClientInterface c = (ClientInterface) Naming.lookup("//" + IP + "/WClient" + IP + "_"
                + uID);
        int newID = clients.size();
        clients.add(c);
        c.setUserID(newID);

    } catch (Exception e) {
        e.printStackTrace();
    }
}
}

并且,在主函数中:

new Server();
Thread.sleep(1000);
new Client();

Thread.sleep(1000);
new Client();

Thread.sleep(1000);
new Client();

接口由

定义
public interface ServerInterface extends Remote...

RMI 设置

public class GenericRMI implements Remote, Serializable {
protected Registry registry;

public void setUpRMI(String bindName) {
    if (registry == null) {
        try {
            registry = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
        } catch (ExportException e) {
            // client and server on one PC
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    try {
        Naming.rebind(bindName, this);
    } catch (RemoteException | MalformedURLException e) {
        e.printStackTrace();
    }
    System.out.println("Started " + bindName);
}
}

然而,输出是这样的

Started WServer
Started WClient192.168.2.124_501
got my ID from the server: 0
Started WClient192.168.2.124_655
got my ID from the server: 0
Started WClient192.168.2.124_771
got my ID from the server: 0

即使我调试它,服务器对每个客户端都有不同的 ID。我想我在某个地方犯了一个可怕的错误,因为我曾经认为服务器只会运行一个实例。我怎样才能做到这一点?

编辑 问题是;如果我调试 registerNewClient() 函数,则每个客户端的相应服务器对象都会更改: 服务器@7728992 服务器@5fbb71ac ... 即使我使客户列表同步,也无济于事。但是,将clients字段设置为transient server端会导致其上出现空指针异常,表明它确实是一个新实例。

【问题讨论】:

    标签: java rmi


    【解决方案1】:

    您确实只有一个实例正在运行。您只调用了一次new Server(),无论如何,三个实例无法绑定到注册表中的同一个名称。您更有可能在未同步的“客户”集合上遇到并发问题。

    【讨论】:

    • 问题是;如果我调试 registerNewClient() 函数,则每个客户端的相应服务器对象都会更改: Server@7728992 Server@5fbb71ac ...即使我使客户端的列表同步,它也无济于事。但是,将clients字段设置为transient server端会导致其上出现空指针异常,表明它确实是一个新实例。
    • 您需要使 GenericRMI 扩展 UnicastRemoteObject。在运动中,它根本不是一个远程对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 2015-07-04
    • 2016-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多