In this example 2 clients send information to each other through a server. One client sends the server a number which is relayed to the second client. The second client halves the number and sends it back to the first client through the server. The first client does the same. The server stops the communication when the number returned to it by any of the clients is less than 10. The return value from the server to the clients (the number it got converted to string representation) then backtracks the process.
login
method with its information. Then:
logout
method (unused in this example).passInt
with the name of the recipient client and an int
.half
on the recipient client with that int
. This initiates a back-and-forth (calls and callbacks) communication until stopped by the server.The login server:
package callbackRemote;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RemoteLogin extends Remote {
RemoteConnection login(String name, RemoteClient client) throws RemoteException;
}
The server:
package callbackRemote;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RemoteConnection extends Remote {
void logout() throws RemoteException;
String passInt(String name, int i) throws RemoteException;
}
The client:
package callbackRemote;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RemoteClient extends Remote {
void half(int i) throws RemoteException;
}
The login server:
package callbackServer;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.Map;
import callbackRemote.RemoteClient;
import callbackRemote.RemoteConnection;
import callbackRemote.RemoteLogin;
public class LoginServer implements RemoteLogin {
static Map<String, RemoteClient> clients = new HashMap<>();
@Override
public RemoteConnection login(String name, RemoteClient client) {
Connection connection = new Connection(name, client);
clients.put(name, client);
System.out.println(name + " logged in");
return connection;
}
public static void main(String[] args) {
try {
Registry reg = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
LoginServer server = new LoginServer();
UnicastRemoteObject.exportObject(server, Registry.REGISTRY_PORT);
reg.rebind("LoginServerName", server);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
The server:
package callbackServer;
import java.rmi.NoSuchObjectException;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.server.Unreferenced;
import callbackRemote.RemoteClient;
import callbackRemote.RemoteConnection;
public class Connection implements RemoteConnection, Unreferenced {
RemoteClient client;
String name;
public Connection(String name, RemoteClient client) {
this.client = client;
this.name = name;
try {
UnicastRemoteObject.exportObject(this, Registry.REGISTRY_PORT);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void unreferenced() {
try {
UnicastRemoteObject.unexportObject(this, true);
} catch (NoSuchObjectException e) {
e.printStackTrace();
}
}
@Override
public void logout() {
try {
UnicastRemoteObject.unexportObject(this, true);
} catch (NoSuchObjectException e) {
e.printStackTrace();
}
}
@Override
public String passInt(String recipient, int i) {
System.out.println("Server received from " + name + ":" + i);
if (i < 10)
return String.valueOf(i);
RemoteClient client = LoginServer.clients.get(recipient);
try {
client.half(i);
} catch (RemoteException e) {
e.printStackTrace();
}
return String.valueOf(i);
}
}
The client:
package callbackClient;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import callbackRemote.RemoteClient;
import callbackRemote.RemoteConnection;
import callbackRemote.RemoteLogin;
public class Client implements RemoteClient {
RemoteConnection connection;
String name, target;
Client(String name, String target) {
this.name = name;
this.target = target;
}
public static void main(String[] args) {
Client client = new Client(args[0], args[1]);
try {
Registry reg = LocateRegistry.getRegistry();
RemoteLogin login = (RemoteLogin) reg.lookup("LoginServerName");
UnicastRemoteObject.exportObject(client, Integer.parseInt(args[2]));
client.connection = login.login(client.name, client);
} catch (RemoteException | NotBoundException e) {
e.printStackTrace();
}
if ("Client1".equals(client.name)) {
try {
client.connection.passInt(client.target, 120);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
@Override
public void half(int i) throws RemoteException {
String result = connection.passInt(target, i / 2);
System.out.println(name + " received: \"" + result + "\"");
}
}
Running the example:
Client2 Client1 1097
.Client1 Client2 1098
.The outputs will appear in 3 consoles since there are 3 JVMs. here they are lumped together:
Client2 logged in
Client1 logged in
Server received from Client1:120
Server received from Client2:60
Server received from Client1:30
Server received from Client2:15
Server received from Client1:7
Client1 received: "7"
Client2 received: "15"
Client1 received: "30"
Client2 received: "60"