RMI for multiple network interfaces
Hello, Habr!
In the course of work, the task appeared to create several RMI registries accessible through different network interfaces (local network and Internet). And to my surprise, I really did not find anything on the network on this issue. Therefore, having figured it out myself, I decided to share the solution with people.
We get two RMI registries, each accessible from its own interface. For additional registry isolation, you can also write your own RMIClientSocketFactory and RMIServerSocketFactory implementations to configure sockets to listen on only given addresses. But I leave it for independent study.
In the course of work, the task appeared to create several RMI registries accessible through different network interfaces (local network and Internet). And to my surprise, I really did not find anything on the network on this issue. Therefore, having figured it out myself, I decided to share the solution with people.
Given
Server with two network interfaces: local and external IP addresses. The interface used by the client and implemented by the server:public interface Server extends Remote {
public String getMessage() throws RemoteException;
}
Task
Create two RMI registries, each for its own network interface.Decision
I’ll immediately make a reservation that it is understood that the reader is familiar with the basics of RMI (if not, you can read it here , here and here ). When creating the registry, it registers to the address specified in the java.rmi.server.hostname parameter. Therefore, we will set our hostname value before creating each registry. To access from the Internet, it is important to remember that RMI uses 2 ports: one for the registry, one for the object. Those. You need to open access from the Internet to two ports. If you do not specify a port when creating an object, then it will be created on an anonymous port, which may not be accessible from the Internet. So, the steps are as follows:- We write the implementation of the interface with the port;
- Create a registry for the local network;
- Create an object and register it in the registry;
- Pass the value of the external IP address to java.rmi.server.hostname;
- Create a registry for an external network on one of the open ports;
- We create an object for an external network on the second of the open ports and register it in the registry;
- Profit
Interface implementation
It is important that in the implementation of the interface, the port is indicated in the constructor.public final class ServerImpl extends UnicastRemoteObject implements Server {
public ServerImpl(int port) throws RemoteException {
super(port);
}
@Override
public String getMessage() throws RemoteException {
return "hello";
}
}
Create registries
Registry localRegistry = LocateRegistry.createRegistry(localPort); //создаем реестр для локальной сети
ServerImpl localEngine = new ServerImpl(0); //создаем объект для локальной сети
registry.rebind("rmi://localServer", localEngine);//регистрируем объект в реестре
System.setProperty("java.rmi.server.hostname", "внешний IP-адрес"); //Устанавливаем внешний IP-адрес в java.rmi.server.hostname
Registry registry = LocateRegistry.createRegistry(remotePort1); //создаем реестр для внешней сети на одном из открытых портов
ServerImpl engine = new ServerImpl(remotePort2); //создаем объект для внешней сети на втором открытом порту
registry.rebind("rmi://remoteServer", engine); //регистрируем объект в реестре
We get two RMI registries, each accessible from its own interface. For additional registry isolation, you can also write your own RMIClientSocketFactory and RMIServerSocketFactory implementations to configure sockets to listen on only given addresses. But I leave it for independent study.