Using RMI Socket Factory to bypass firewall.

Hello all.

I just finished developing a server/client application that uses RMI.

Everything works great without firewall,

But when the firewall is on ..... the server can't callback methods on the client side.

On the client side, I'm writing these lines:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

myRegistry = LocateRegistry.createRegistry(1099);

myRegistry.rebind(clientName,this);

String regName = "//"+serverAddress+"/S-ervice";

server = (serverSide.Server)java.rmi.Naming.lookup(regName);

String result = server.login(myDetails);

On the server side, I'm writing these lines:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

registry = LocateRegistry.createRegistry(1099);

registry.rebind("S-ervice", this);

String regName = "//" + details.getIP() + "/"+details.getUserName();

*** clientNumberOne=(clientSide.Client) java.rmi.Naming.lookup regName);

As I said, if the client is NOT behind firwall - everything works great.

if the client behind firewall - the line marked with *** throws exception:

java.rmi.ConnectException: Connection refused to host: 84.229.32.82; nested exception is:

java.net.ConnectException: Connection timed out: connect

at sun.rmi.transport.tcp.TCPEndpoint.newSocket(Unknown Source)

at sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source)

at sun.rmi.transport.tcp.TCPChannel.newConnection(Unknown Source)

at sun.rmi.server.UnicastRef.newCall(Unknown Source)

at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)

at java.rmi.Naming.lookup(Unknown Source)

at serverSide.ServerImpl.login(ServerImpl.java:89)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

at java.lang.reflect.Method.invoke(Unknown Source)

at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)

at sun.rmi.transport.Transport$1.run(Unknown Source)

at java.security.AccessController.doPrivileged(Native Method)

at sun.rmi.transport.Transport.serviceCall(Unknown Source)

at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)

at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)

at java.lang.Thread.run(Unknown Source)

Caused by: java.net.ConnectException: Connection timed out: connect

at java.net.PlainSocketImpl.socketConnect(Native Method)

at java.net.PlainSocketImpl.doConnect(Unknown Source)

at java.net.PlainSocketImpl.connectToAddress(Unknown Source)

at java.net.PlainSocketImpl.connect(Unknown Source)

at java.net.SocksSocketImpl.connect(Unknown Source)

at java.net.Socket.connect(Unknown Source)

at java.net.Socket.connect(Unknown Source)

at java.net.Socket.<init>(Unknown Source)

at java.net.Socket.<init>(Unknown Source)

at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(Unknown Source)

at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(Unknown Source)

... 18 more

As I saw in the forum, I can use sockets to solve my problem.

The thing is that I got confuse ... there is too much irrelevant information!

Should I have sockets in both sides ?

If I need two sockets,

Should I use one class for both ?

Or both sockets are different and I need to use two different classes ?

When the client tries to connect to server,

should it look for the socket ?

How do I call getRegistry/createRegistry with sockets ?

There are few main examples on the net (that everybody uses them),

but they not good for me.

By the way,

My client's application uses web start (*.jnlp)

so I don't know if I can use a solution with "java -Djava ... "

Waiting for your replay ...

p.s.

Is using sockets is the best solution ?

I don't mine using proxy as long as it will work !!!

Help ...

[4111 byte] By [Ron1979a] at [2007-10-3 2:52:59]
# 1
http://java.sun.com/j2se/1.3/docs/guide/rmi/rmisocketfactory.doc.html
el_doradoa at 2007-7-14 20:42:02 > top of Java-index,Core,Core APIs...
# 2

Thanks for replaying but unfortunately, I saw this page before ...

This example too much complicated...

13 classes without the policy file ....

And I need to use the command " java -Djava.security.policy= .... "

All I want is to pass number from client to server :(

I need something much more simple !

Can you write something simple or give me a specific description of

what I should do ?

Ron1979a at 2007-7-14 20:42:02 > top of Java-index,Core,Core APIs...
# 3
Here is one [url= http://wiki.java.net/bin/view/Communications/FirewalledClients]example[/url]. Once you learn the [url= http://wiki.java.net/bin/view/Communications/TransparentProxy]basics[/url] it can be surprisingly easy to do.Good
cajoa at 2007-7-14 20:42:02 > top of Java-index,Core,Core APIs...
# 4

Hi Cajo

That's a simple example

(for those who want to use your library file).

But what if I want to write the whole source by myself... ?

I read your source files... it's a masterpiece !!!

But I don't think I need all of that....

Don't get me wrong - I think you are awesome !!!

And up to now, you are the only one that can help me...

Please do so ...

I'm trying to understand this for almost a month !!!

If you can, just tell me what to do step by step and it will be great.

if you'll add few blocks of code it will be completely awesome ....

Anyway, I'll am happy to award you my first duke

I hope that in the future i'll give you more...

Waiting impatiently for your replay.

Ron1979a at 2007-7-14 20:42:02 > top of Java-index,Core,Core APIs...
# 5

If you have the time to spare, to do it by yourself provides an exceptional learning opportunity. I highly encourage you!

If you look at the interaction between ItemProxy and ClientProxy, what is happening is that the client is invoking a method on the server. The server method blocks the client's thread, until it has some data to provide the client.

This effectively enables instantaneous asynchronous server callbacks to a firewalled client. It has one important limitation however; the server cannot callback the client reentrantly. In other words, the server must wait for the callback to complete, before invoking another, for the given client object.

For most people, this is an acceptable limitation, for the sake of great simplicity. Reentrant asynchronous callbacks to a firewalled client is a guru task. (Java Level 9) I hope that is what not you are looking for just yet.

John

PS I expect, step by step, your code will grow until it matches the cajo project, as the usual obstacles pop up, like NAT, and HTTP proxies. I wish you an excellent and educational journey!

cajoa at 2007-7-14 20:42:02 > top of Java-index,Core,Core APIs...
# 6

well, as I see it I don't need all of that code,

for e.x : the method zedmob on Remote.java

it deals with GZIPInputStream.

I'll explain myself better:

I'm running a server on home PC.

Everyone who will download my client will interact with my home PC.

I have constant IP address so in the client's code,

I wrote that the client should connect to a specific IP.

The server algorithm goes like this:

*) client number 1 has logged in (with name, pass, ip address).

The server will look up for the client using this command:

String regName = "//" + details.getIP() + "/"+details.getUserName();

clientNumberOne=(clientSide.Client) java.rmi.Naming.lookup regName);

**) client number 2 has logged in (with name, pass, ip address).

The server will look up for him :

String regName = "//" + details.getIP() + "/"+details.getUserName();

clientNumberTwo=(clientSide.Client) java.rmi.Naming.lookup regName);

After the server will have both players,

It will create new thread using the parameters:

clientNumberOne, clientNumberTwo.

This thread is responsible on the game's steps and the game's result.

My application works both direction:

The client can callback the server and the server can callback the client.

My problem is with the client's firewall.

if it's down - the game is working perfectly.

If the client is behind firewall, the server cant execute the lines:

*** clientNumberOne=(clientSide.Client) java.rmi.Naming.lookup regName);

*** clientNumberTwo=(clientSide.Client) java.rmi.Naming.lookup regName);

(when regName = "//" + details.getIP() + "/"+details.getUserName();)

Now, I thought to open a socket on the client's side,

and the server will interact with this socket.

Is that possible ?

Should I have socket on the server side too ?

should I create a proxy ?

how do I create a proxy ?

is it like this :

System.setProperty("proxySet", "true");

System.setProperty("http.proxyHost", proxyHost);

System.setProperty("http.proxyPort", Integer.toString(proxyPort));

or is it like this :

System.setProperty("java.rmi.server.useLocalHostname", "true");

System.setProperty("java.rmi.server.hostname", rcsf.host);

Which address I should write in the proxy ?

I don't think I need to write 10 files in order to create proxy/socket.

cajo - please help me....

P.S

There is a post on smart proxy.

does it also bypass firwalls ?

if it does, is it more simple then sockets ?

Ron1979a at 2007-7-14 20:42:02 > top of Java-index,Core,Core APIs...
# 7

> I don't think I need to write 10 files in order to create proxy/socket.

You are losing track of the second-order encapsulation provided by Java packages. You are going to get overwhelmed. Even when you open a socket, you are actually instantiating dozens of objects, in many packages, and using countless native functions of the underlying operating system. The whole point is that you don't have to think about it. The object you are using simply does what is says it going to do. This is how we manage complexity in Java. This is why the ItemProxy / ClientProxy example looks so impossibly simple, and as I hope you've noticed, it works too.

I understand your problem perfectly, it is a very common issue.

OK, last time:

In one thread your client asynchronously calls the server, exactly as you do now. However, your client needs to launch another thread, to invoke a method on the server, let's say: reverseCallback, for example.

This invocation would be blocked at the server, until the server had data to return. The method would immediately return at the client with the result. The client thread would process this data, and immediately call reverseCallback again, and hang until further data was available.

The nice thing about this approach is that once you have it working, it functions both with clients that are firewalled, and ones that are not.

Good luck.

cajoa at 2007-7-14 20:42:02 > top of Java-index,Core,Core APIs...
# 8
OK cajo.I'll do my best.I hope to write here a nice solution about this well known problem.Wish me luck.
Ron1979a at 2007-7-14 20:42:02 > top of Java-index,Core,Core APIs...
# 9
I am sure you can do it. Best wishes, of course.
cajoa at 2007-7-14 20:42:02 > top of Java-index,Core,Core APIs...
# 10

Hello,

MyName Andrey Borovik.

I am developing completely similar your a server/client application and I met the same problem.

Could I ask you a few questions.

1.Have you solved this problem?

2. If so could you send me the source?

3. Does your solution permits support connection between server and user if user machine behind router or if user has wireless connection?

I really appreciate if help me .

I will be very glad to interact with for solution different problems that may be appear in future.

Sincerely Andrey

elanjonathana at 2007-7-14 20:42:02 > top of Java-index,Core,Core APIs...
# 11
AndreySee cajo's project cited above for a freeware solution.For a supported commercial solution see my RMI Proxy product at http://www.telekinesis.com.au
ejpa at 2007-7-14 20:42:02 > top of Java-index,Core,Core APIs...