NAT, RMI, -Djava.rmi.server.hostname, is there a client solution instead?
Oct 25, 2006 1:57 AM
NAT=Network Address Translation.
Problem: Using RMI. The java.rmi.server.hostname directive is used on the server side when NAT'ing of the ip-addresses between client and server occur. Problem is that I can have several NAT'ed clients (each with different NAT address to the server) to the single RMI server. So in principle I do not know beforehand what NAT address the server gets on the client side.
Question: Is there a client solution to the NAT problem instead of a server solution?
Details:
I have a RMI server that perform the following bind:
Naming.rebind("RMI-SERVER",theServerObject);
The client perform the following lookup:
Naming.lookup("rmi://XXX.18.26.111/RMI-SERVER");
The client need to connect through a NAT router and so the ip-address is translated to YYY.4.233.101.
I get the following message:
Error in the remote invocation java.rmi.ConnectException: Connection refused to host: YYY.4.233.101; nested exception is:
java.net.ConnectException: Connection timed out: connect
To avoid the message I need, on the server side to call my server with the following directive:
-Djava.rmi.server.hostname=XXX.18.26.111
Then it works.
It appear to me that the ip-address is both used as a part of the identification of the remote object as well as to identify which server to direct my tcp/ip packages.
Problem is that IP-layer communication and the higher level protocol RMI is combined in one call.
This is why the server needs to know the NAT address used on the client side beforehand.
So if I on the client side could define the ip-address on the ip-layer and the ip-address on the RMI layer differently then a client solution to the NAT problem would exist. I could then let my server just registrate with its own local ip and let the client use the NAT address on the ip-layer and the un-NAT'ed address on the RMI layer.
I don't even understand your problem. java.rmi.server.hostname provides a solution for the address translation that takes place during server-side NAT. If the server needs to know the client address, which would only be true if there are client-side callbacks and clients are behind NAT devices, then java.rmi.server.hostname at the client provides the same answer to the same problem the other way around.
Re: NAT, RMI, -Djava.rmi.server.hostname, is there a client solution inste
Oct 26, 2006 7:16 AM
(reply 2
of 5) (In reply to
#1 )
Yes you are correct. However what I discovered is that if I do it ip-based it does not work. If I do it DNS name based then it works!
So on my client PC I do the following:
1. Add to my hosts file on the client PC:
rmi_server.zone1 XXX.18.26.111
2. In the java program on my client I do:
Naming.lookup(rmi://rmi_server.zone1/RMI-SERVER);
3. On the bat-file on the client side I add the directive:
-Djava.rmi.server.hostname=rmi_server.zone1
4. The server has the host name rmi_server.zone1. When starting the rmi server in the server side I add the directive:
-Djava.rmi.server.hostname=rmi_server.zone1
If I instead replaced rmi_server.zone with ip address XXX.18.26.111 in step 3 and the local ip address YYY.4.233.101 then it does not work (Beware it is impossible to start the server up having Djava.rmi.server.hostname=XXX.18.26.111).
When I look on a trace I can see that the ip-address is build into the Unicast Reference. Using the dns name as hostname instead makes the Unicast Reference the same on both client and server side and the clients accepts the reference. If the Unicast reference differs the client will not accept the object.
Conclusion is that you are right, just with the small twist that dns names shall be applied.
Of course a Duke Dollar is on the way to your bucket!
Re: NAT, RMI, -Djava.rmi.server.hostname, is there a client solution inste
Oct 26, 2006 4:09 PM
(reply 3
of 5) (In reply to
#2 )
Step 3 does nothing unless you have callbacks in your client. java.rmi.server.hostname tells RMI what hostname or IP address to use for servers exported from the current JVM. If your client doesn't export callbacks, setting it at the client is pointless.
Re: NAT, RMI, -Djava.rmi.server.hostname, is there a client solution inste
Feb 18, 2007 12:35 PM
(reply 4
of 5) (In reply to
#3 )
I tried the same thing, but when I add that parameter to the JVM command when starting the server, it hangs on the Naming.rebind call. The server machine is behind a Linksys router using NAT. The client is on a private corporate network that is not blocking rmi's default port 1099.
MyRemoteObj mro = new MyRemoteObj();
Naming.rebind ("MROServ", mro);
When I don't use that parameter and (from the client) print the toString for the stub returned by Naming.lookup, I get this. It seems to show that this is the same problem that we're talking about, with the unroutable IP:
[RemoteStub [ref: [endpoint:[192.168.1.101:57164](remote),objID:[3327eef2:110d688aa21:-8000, 0]]]]
mydomain.com looks like a domain name to me, not a hostname, and therefore it is not an IP address at all. It has to be a hostname or IP address of the host in which the JVM is running that is reachable by the client (and also by the Registry). Or the hostname/IP address of a NAT device which is forwarding that port to this host.
But the only way you can get a connect exception talking to the Registry is if you supply the wrong hostname or IP address to Naming.bind()/rebind() or Registry.getRegistry(). The only sensible value to use in any of these cases is 'localhost', as the Registry has to be local for the bind to succeed.