I'm learning RMI, and wondering that if it is possible to start two servers with different ports, and how to implement it?
The programme has one client and two servers. Server1 uses the RMI default port 1099. Server2 uses the port 1098 (I have checked the port 1098 is not in use).
Server1:
public static void main(String[] args) {
try {
Server obj = new Server();
Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0);
Registry registry = LocateRegistry.getRegistry();
registry.bind("Hello", stub);
System.out.println("Server 1 ready");
} catch (Exception e){
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
Server2
public static void main(String[] args) {
try {
ServerTwo obj = new ServerTwo();
HelloTwo stub = (HelloTwo) UnicastRemoteObject.exportObject(obj, 0);
Registry registry = LocateRegistry.createRegistry(1098);
registry = LocateRegistry.getRegistry(1098);
registry.bind("HelloTwo", stub);
System.out.println("Server 2 ready");
} catch (Exception e){
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
Compile and run server:
javac *java
rmic Server
rmiregistry 1099 &
rmic ServerTwo
rmiregistry 1098 &
By the way, the process name in port 1099 and 1098 is different.
I checked the port by lsof -i tcp:portnumber
and found there are two process in port 1099 and 1098 respectively. But the port 1099 shows the name is *:rmiregistry (LISTEN)
. The port 1098 shows the name is *:rmiactivation (LISTEN)
. Why they are different? What does this mean? Does this relate to the following error?
When start the Server2, error is following:
Server exception: java.rmi.server.ExportException: Port already in use: 1098; nested exception is:
java.net.BindException: Address already in use
java.rmi.server.ExportException: Port already in use: 1098; nested exception is:
java.net.BindException: Address already in use
at sun.rmi.transport.tcp.TCPTransport.listen(TCPTransport.java:341)
at sun.rmi.transport.tcp.TCPTransport.exportObject(TCPTransport.java:249)
at sun.rmi.transport.tcp.TCPEndpoint.exportObject(TCPEndpoint.java:411)
at sun.rmi.transport.LiveRef.exportObject(LiveRef.java:147)
at sun.rmi.server.UnicastServerRef.exportObject(UnicastServerRef.java:208)
at sun.rmi.registry.RegistryImpl.setup(RegistryImpl.java:152)
at sun.rmi.registry.RegistryImpl.<init>(RegistryImpl.java:137)
at java.rmi.registry.LocateRegistry.createRegistry(LocateRegistry.java:203)
at ServerTwo.main(ServerTwo.java:20)
Caused by: java.net.BindException: Address already in use
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:382)
at java.net.ServerSocket.bind(ServerSocket.java:375)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:128)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createServerSocket(RMIDirectSocketFactory.java:45)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createServerSocket(RMIMasterSocketFactory.java:345)
at sun.rmi.transport.tcp.TCPEndpoint.newServerSocket(TCPEndpoint.java:666)
at sun.rmi.transport.tcp.TCPTransport.listen(TCPTransport.java:330)
... 8 more
It shows the port 1098 is in use... Yes, Server2 use the port... how to solve it? I'm confused about the RMI and port connection.
=============
Edit:
Add Client code:
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");
String response = stub.sayHello();
System.out.println("response 1: " + response);
HelloTwo stub2 = (HelloTwo) registry.lookup("HelloTwo");
String response2 = stub2.sayHello();
System.out.println("response 2: " + response2);
} catch (Exception e) {
System.err.println("Client exception: " + e.toString());
e.printStackTrace();
}
}
You don't need two Registries. You don't even need two ports, if the Registry and the remote obects are all created by the same JVM. You just need to:
LocateRegistry.createRegistry(Registry.REGISTRY_PORT)
In that way, everything will be listening on port 1099.
The port 1098 shows the name is
*:rmiactivation (LISTEN).
Why they are different?
Because port 1098 is reserved for the RMI Activation Daemon, and that is all that lsof
knows about it.