Question

I am currently trying to grab the basics of RMI by implementing a Server/Client Structure where both the Client can invoke remote Operations on the Server, and the Server can invoke Client functions:

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

and, in the main function:

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

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

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

interfaces are defined by

public interface ServerInterface extends Remote...

RMI setup

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

however, output is like

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

even if i debug it, the server has a different ID for each client. I guess I am doing a terrible mistake somewhere, since I used to think that the server would only have ONE instance running. How can I achieve that?

EDIT the Problem is; if i debug the registerNewClient() function, the respective Server object changes for each Client: Server@7728992 Server@5fbb71ac ... Even if i make the clients' list synchronized, it doesn't help. However, making the clients field transient server-side leads to a null pointer exception on it, indicating that it indeed is a new instance.

Was it helpful?

Solution

You do have only one instance running. You only called new Server() once, and in any case there's no way three instances can be bound to the same name in the Registry. More likely you have a concurrency problem on the unsynchronized 'clients' collection.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top