RMI Callbacks and DHCP/NAT

Hello all,

I hate to beat this topic to death but I have not been able to find a satisfactory answer. I had client/server application that is implemented by sockets and I have been trying to put it into the RMI framework. Everything seems to work quite fine on the LAN. The problem is for clients that have a dynamic address and are behind a NAT.

I basically get the the "java.net.SocketException: Network is unreachable"

when the server tries to fire a callback to the client.

Everything works fine if the client has a static ip. I did not have this problem with sockets because the socket connection would allow the server to easily send messages back to clients behind a NAT.

I am using a RMI SocketFactory, specfically the SslRMISocketFactory. I also

do the typical passing a client reference to the RMI server for callbacks.

I have checked all the threads and noticed that setting the java.rmi.server.hostname property worked for some users, I set that and it didnt work for me.

Another idea I had was that I could just open a tcp socket just to handle callbacks, so in that way a stateful connection is maintained, but I would like to avoid opening another port/connection.

I also noticed that the cajo project is mentioned, has anyone had any luck with using this? Will it work if a client has a dynamic ip and is behind a NAT? Also will it support using SslRMIClientSocketFactory()/SslRMIServerSocketFactory() ?

I really like the advantages RMI is providing me in terms of Object Orientation, so I would appreciate it if anyone could give me some useful feedback/comments/suggestions to get over this problem.

cheers

Tom

[1707 byte] By [tmolina7000a] at [2007-10-2 22:00:03]
# 1
You have to set java.rmi.server.hostname at the client JVM to the public IP address of the NAT box, and you have to arrange with the NAT box to forward the appropriate port to the client. This technique does work.
ejpa at 2007-7-14 1:16:16 > top of Java-index,Core,Core APIs...
# 2
Ok I will have a chance to try this out tommorrow. But I guess I was hoping for a solution in which no changes would be needed to any NAT boxes. But I will have a chance to try this out tommorrow.
tmolina7000a at 2007-7-14 1:16:16 > top of Java-index,Core,Core APIs...
# 3

I sympathise with what you are saying about configuring NAT boxes.

I run an RMI project on Sun's java.net site that, amongst other things, can [url=http://wiki.java.net/bin/view/Communications/FirewalledClients]callback firewalled clients[/url], which seems to be exactly what you are looking for.

It's called [url=https://cajo.dev.java.net]the cajo project[/url], perhaps it can be of help to you.

John

cajoa at 2007-7-14 1:16:16 > top of Java-index,Core,Core APIs...
# 4
You can't have a solution that doesn't involve changing NAT boxes as the issues concerned are part of their function.
ejpa at 2007-7-14 1:16:16 > top of Java-index,Core,Core APIs...
# 5

Hi John,

thanks for you response. I have been implementing the solution you have suggested. I actually found a similiar solution of using thread blocking, but the classes that you suggested I use make it very simple. I hope you dont mind if I bother you with some questions in the future.

thanks

Tom

tmolina7000a at 2007-7-14 1:16:16 > top of Java-index,Core,Core APIs...
# 6
No problem Tom, anytime.Good luck, and most importantly, have fun!John
cajoa at 2007-7-14 1:16:16 > top of Java-index,Core,Core APIs...
# 7

Hi John,

I have been able to integrate your CientProxy example from : http://wiki.java.net/bin/view/Communications/FirewalledClients.

I am following it very closely in fact.

I did have two questions though wrt Cajo:

1) I got the implementation down, but I wanted to make sure I was implementing the cajo framework correctly. I have been setting up my RMI framework as I have normally been doing in that I create the following:

registry = LocateRegistry.createRegistry(port);

RMIClientSocketFactory rmiClientSocketFactory = new SslRMIClientSocketFactory();

RMIServerSocketFactory rmiServerSocketFactory = new SslRMIServerSocketFactory();

MyInterface myinterface = (MyInterface) UnicastRemoteObject.exportObject(this, 0, rmiClientSocketFactory, rmiServerSocketFactory);

registry.rebind(serviceName, myinterface);

when I register the callback server service though I do a

Remote.config(ipaddress, port+1, ipaddress, port+1);

ItemServer.bind(this, "CajoServer");

basically follwing your server code for callbacks

So from my understanding is that I have one Port for issuing rmi commands

and another port for receiving callbacks. Or is there a way to combine

my invocation of commands and receiving callbacks to one port?

I am still a bit of a rookie with RMI but I do know that it uses a port range

so I also wanted to make sure it would not interfere with callbacks in any way.

2) I wanted to make the server portion to support multiple clients. As I have many clients that will need to connect to my server. So far I have following the RMI callback model in that I keep an ArrayList of the ClientProxies. So I execute a Object result = Remote.invoke(cp, "Callback", new Object[] {sender, msg, filter, color}); for each ClientProxy(ie client) that was registered in the ArrayList. I was thinking of spawning a thread for each of these invocations so that each of the clients doesnt have to wait for the previous invocations to the other clients to happen. I assume there is a better approach with cajo framework so I was hoping you could provide me with some pointers on how to make it a bit more robust and multithreaded for handling callbacks to multiple clients.

I appreciate any feedback you can give me. Sorry for so many questions.

I am very excited to get it all working as efficient as possible.

thanks

Tom

tmolina7000a at 2007-7-14 1:16:16 > top of Java-index,Core,Core APIs...
# 8

Tom,

You can either configure the rmiregistry explicitly, or perform the Remote.config and ItemServer.bind operations. There is no need to do both.

You can use the same port for both remote invocations, and client callbacks. I would recommend using port 1198 as it is assigned for cajo remote object communication.

Initially I suggest not doing the explicit registry configuration. Just until things are working the way you like. This means of course that plaintext socket factories will be used. Perhaps it is time to consider official support for TLS encrypted socket factories. If you really need SSL sockets right now, just edit the gnu.cajo.invoke.Remote file to use them instead of conventional RMI SocketFactories.

You can use the [url=https://cajo.dev.java.net/docs/gnu/cajo/utils/extra/AsyncMethod.html]gnu.cajo.utils.extra.AsyncMethod[/url] class to call back the clients asynchronously. Make sure to listen for invocation exceptions, it will indicate that it is time to take the ClientProxy out of the ArrayList.

No problem at all about the questions, however, I recommend posting cajo questions at the [url=https://cajo.dev.java.net/servlets/ProjectForumView]project forum[/url], as this forum is intended to be a discussion centre for Java RMI in general.

John

cajoa at 2007-7-14 1:16:16 > top of Java-index,Core,Core APIs...
# 9
thanks for your quick feedback John. I will also post future questionsin the forum.thanksTom
tmolina7000a at 2007-7-14 1:16:16 > top of Java-index,Core,Core APIs...