Clarification on firewall issues with Java networking APIs

Q

Qu0ll

I understand that RMI doesn't play well with the internet because it can't
work properly when either the client or the server is behind a proxy unless
tunneling is used and that tunneling is slow and prevents callbacks from
being used. So I get it that RMI is probably not the network API for me.

And I understand that servlets don't have this problem because they
communicate through the standard HTTP port but that servlets don't support
callbacks for non-HTML clients. (Feel free to disagree if appropriate).

Which leads me back to NIO. Does it suffer the same problems as RMI?
Namely, will it play well if the client is behind a proxy? If so, why is it
that RMI can't and NIO can?

--
And loving it,

-Q
_________________________________________________
(e-mail address removed)
(Replace the "SixFour" with numbers to email me)
 
A

Arne Vajhøj

Qu0ll said:
I understand that RMI doesn't play well with the internet because it
can't work properly when either the client or the server is behind a
proxy unless tunneling is used and that tunneling is slow and prevents
callbacks from being used. So I get it that RMI is probably not the
network API for me.

It is difficult but possible to get RMI through an opened port in
a firewall.

A proxy server that only knows HTTP seems as a total roadblock for
RMI to me.
And I understand that servlets don't have this problem because they
communicate through the standard HTTP port

The proxy server understands HTTP and forward those. Note that in
most cases client/server via HTTP through proxy server will only
work if it is on the client side.
but that servlets don't
support callbacks for non-HTML clients. (Feel free to disagree if
appropriate).

It is not obvious to me what you mean with callbacks. But most
certainly the servlet does not care what type of client is requesting.
Which leads me back to NIO. Does it suffer the same problems as RMI?
Namely, will it play well if the client is behind a proxy?

NIO is an API not a protocol.

Plain sockets (both normal and via NIO) will usually only be able
to go out through a proxy server if they emulate the HTTP protocol.

I you need something network allowable, then look for web services
(SOAP/HTTP).

Arne
 
Q

Qu0ll

Thanks for your reply Arne - comments inline.
It is difficult but possible to get RMI through an opened port in
a firewall.

A proxy server that only knows HTTP seems as a total roadblock for
RMI to me.

Right, so RMI is definitely out then.
It is not obvious to me what you mean with callbacks. But most
certainly the servlet does not care what type of client is requesting.

By callbacks I mean something like "push" technology where the servlet is
able to send data to the client without the client having had to request it.
This is critical to my project and hence I have discounted servlets as a
possible solution for their inability to do this. Are you saying that there
is a way to have push functionality from a servlet to an applet?
Plain sockets (both normal and via NIO) will usually only be able
to go out through a proxy server if they emulate the HTTP protocol.

I am not sure I entirely understand this... how do I have my NIO server and
client emulate the HTTP protocol?
I you need something network allowable, then look for web services
(SOAP/HTTP).

OK, this is something I hadn't considered. Is it feasible and/or practical
to invoke web services from applets? It has to be applets and not Web
Start.

--
And loving it,

-Q
_________________________________________________
(e-mail address removed)
(Replace the "SixFour" with numbers to email me)
 
A

Arne Vajhøj

Qu0ll said:
By callbacks I mean something like "push" technology where the servlet
is able to send data to the client without the client having had to
request it. This is critical to my project and hence I have discounted
servlets as a possible solution for their inability to do this. Are you
saying that there is a way to have push functionality from a servlet to
an applet?

HTTP does not allow push from server to client.

For push you should go for plain sockets.

And that does (usually) not go through proxy servers.
I am not sure I entirely understand this... how do I have my NIO server
and client emulate the HTTP protocol?

Simply implement the HTTP protocol. It is rather simple to do. But
by doing that you will be limited by the HTTP protocol that
does not allow push.
OK, this is something I hadn't considered. Is it feasible and/or
practical to invoke web services from applets? It has to be applets and
not Web Start.

Yes. If you have a very new Java on the client you may not even need to
download MB's of jars. With older Java then ...

Note that this does not solve the HTTP problem either.

----

From a practical point of view - if you need push then:
- plain sockets
- server app (daemon) on the server side
- firewalls on the client side has to allow outbound connections
- firewall the server side has to get a port opened
- no proxy servers only forwarding HTTP allowed
seems as the possible.

Arne
 
Q

Qu0ll

HTTP does not allow push from server to client.

For push you should go for plain sockets.

And that does (usually) not go through proxy servers.

Usually? Are you saying it can be done?
Simply implement the HTTP protocol. It is rather simple to do. But
by doing that you will be limited by the HTTP protocol that
does not allow push.

OK, no good then. Although there is a thing called Comet which permits
push-style interaction with JSF and JSP I believe but I don't think it would
work with applets(?).
Yes. If you have a very new Java on the client you may not even need to
download MB's of jars. With older Java then ...

Note that this does not solve the HTTP problem either.

So web services can't push either? OK, I get it.
From a practical point of view - if you need push then:
- plain sockets
- server app (daemon) on the server side
- firewalls on the client side has to allow outbound connections
- firewall the server side has to get a port opened
- no proxy servers only forwarding HTTP allowed
seems as the possible.

My ideal solution was RMI but that has been ruled out. So my "next best
fit" is an NIO server daemon and NIO client in the applet with the caveats
that you have outlined above. Now, I am assuming this fits the "plain
sockets" criterion you mentioned - right?

Arne, would you be able to comment on the prevalence of environments where
this would not work such as where there are proxy servers that only allow
HTTP forwarding? i.e. is this a common setup in large businesses perhaps?

--
And loving it,

-Q
_________________________________________________
(e-mail address removed)
(Replace the "SixFour" with numbers to email me)
 
A

Arne Vajhøj

Qu0ll said:
Usually? Are you saying it can be done?

I am saying that normally the proxy does not allow it.

But in theory you could write a proxy server that did.
OK, no good then. Although there is a thing called Comet which permits
push-style interaction with JSF and JSP I believe but I don't think it
would work with applets(?).

Never heard about it, so I can not comment on what they do and don't.
My ideal solution was RMI but that has been ruled out. So my "next best
fit" is an NIO server daemon and NIO client in the applet with the
caveats that you have outlined above. Now, I am assuming this fits the
"plain sockets" criterion you mentioned - right?

Yes. NIO can be used with plain sockets. I really can not see the
need for using NIO at the client.
Arne, would you be able to comment on the prevalence of environments
where this would not work such as where there are proxy servers that
only allow HTTP forwarding? i.e. is this a common setup in large
businesses perhaps?

Yes. It is a typical corporation thing.

The firewall oes not allow outgoing connections directly from
employees PC's.

Instead they can have their browser connect to the proxy server
that forwards HTTP and maybe FTP and nothing else.

Arne
 
Q

Qu0ll

Yes. It is a typical corporation thing.

The firewall oes not allow outgoing connections directly from
employees PC's.

Instead they can have their browser connect to the proxy server
that forwards HTTP and maybe FTP and nothing else.

Is it possible for the Java program (probably at the client end) to detect
that this situation exists? I mean if I default to using RMI, can it detect
that such a proxy system is in place and then revert to using another
method/protocol if it is? I ask this because my testing with RMI and the
other network architectues revealed that RMI gave by far the fastest
response and I would like to use it wherever possible.

--
And loving it,

-Q
_________________________________________________
(e-mail address removed)
(Replace the "SixFour" with numbers to email me)
 
N

Nigel Wade

Qu0ll said:
I understand that RMI doesn't play well with the internet because it can't
work properly when either the client or the server is behind a proxy unless
tunneling is used and that tunneling is slow and prevents callbacks from
being used. So I get it that RMI is probably not the network API for me.

RMI plays perfectly well with the Internet, but not firewalls. I think RMI works
in a very similar way to portmapper. The rmiregistry listens on a well-known
port. A RMI server registers its service with the rmiregistry, and is either
assigned or tells the registry the port that it actually listen on. A RMI
client asks the rmiregistry for the "location" of a particular service, and the
rmiregistry replies telling the client what host/port the server is listening
on.

For the above to work through a firewall the client must be able to connect to
the server both on the rmiregistry port and the port on which the server is
listening. This will normally cause problems with firewalls because they are
not configured to allow this to happen for dynamic ports. It may be possible
for an RMI server to request a specific port and register that, but I'm not
certain (RMISocketFactory.createServerSocket(int port)?). That way it might be
possible to open only the rmiregistry port and the specific RMI server ports in
the firewall.
And I understand that servlets don't have this problem because they
communicate through the standard HTTP port but that servlets don't support
callbacks for non-HTML clients. (Feel free to disagree if appropriate).

Servlets can communicate via any port. The initial connection is made to the
servlet container on whatever port that happens to be listening on. It may be
80, or 8080 or any other port. The socket is passed to the servlet's service
routine and the servlet can send a reply on that already established socket.
There is no requirement for communication to be HTTP unless you extend
HttpServlet. A GenericServlet can use any protocol (layered over TCP/IP).

Servlets can also open any other socket they wish, including initiating callback
to a client. If you do this in the service method you are likely to get
deadlock if the servlet attempts to initiate a new communication channel with
the client whilst the client is waiting for the servlet to respond to its
initial request. You would have to handle this carefully.

You could also start a background thread in the servlet. The background thread
could open a socket to the client and send data when it was ready. The client
would have to be listening to accept the connection and be able to read the
data. But with this method you are at the mercy of the servlet container as it
may decide to unload the servlet if it doesn't received any new service calls.

The simplest method is to use blocking calls. The client makes a service request
to the servlet as normal, but the servlet does not return until there is
something to return. This would presumably require a separate thread in the
client to wait for that service call to return so the main processing of the
client could continue. You would also create one thread per client request in
the servlet, which might also cause problems. However, it requires no
connection from the server back to the client, and maybe your best bet for
getting around the proxy/firewall problem.
Which leads me back to NIO. Does it suffer the same problems as RMI?
Namely, will it play well if the client is behind a proxy? If so, why is it
that RMI can't and NIO can?

I have no experience of proxies so can't help here.
 
R

Roger Lindsjö

Qu0ll said:
OK, no good then. Although there is a thing called Comet which permits
push-style interaction with JSF and JSP I believe but I don't think it
would work with applets(?).

Resin's Comet seems to just be a long (timewise) request to a servlet.
As far as I can tell the application (Applet, JavaScript, etc) initiates
a HTTP request to the server (let's assume a servlet). The servlet
accepts the request, but instead of just returning an answer it hangs on
to the request/response and sends back data as it becomes available.
With Ajax they seem to be sending <script>...</script> as part of each
response as the browser will parse and execute those as they come
without waiting until the request is completed. See
http://www.caucho.com/resin-3.1/examples/servlet-comet/
Something similar could probably be implemented for applets as well.

//Roger Lindsjö
 
A

Arne Vajhøj

Qu0ll said:
Is it possible for the Java program (probably at the client end) to
detect that this situation exists? I mean if I default to using RMI,
can it detect that such a proxy system is in place and then revert to
using another method/protocol if it is? I ask this because my testing
with RMI and the other network architectues revealed that RMI gave by
far the fastest response and I would like to use it wherever possible.

Try send an HTTP request directly to www.google.com, if it fails then
either Google is down or direct outbound HTTP are blocked

Or maybe it makes more sense to actually try and connect to your
server on the correct port just in case 80 is open but your
port is not.

Arne
 
A

Arne Vajhøj

Nigel said:
RMI plays perfectly well with the Internet, but not firewalls. I think RMI works
in a very similar way to portmapper. The rmiregistry listens on a well-known
port. A RMI server registers its service with the rmiregistry, and is either
assigned or tells the registry the port that it actually listen on. A RMI
client asks the rmiregistry for the "location" of a particular service, and the
rmiregistry replies telling the client what host/port the server is listening
on.

For the above to work through a firewall the client must be able to connect to
the server both on the rmiregistry port and the port on which the server is
listening. This will normally cause problems with firewalls because they are
not configured to allow this to happen for dynamic ports. It may be possible
for an RMI server to request a specific port and register that, but I'm not
certain (RMISocketFactory.createServerSocket(int port)?). That way it might be
possible to open only the rmiregistry port and the specific RMI server ports in
the firewall.

It is possible.

RMISocketFactory.setSocketFactory(new FixedPortRMISocketFactory());
LocateRegistry.createRegistry(60000);

and:

package test.server;

import java.io.IOException;
import java.net.Socket;
import java.net.ServerSocket;
import java.rmi.server.RMISocketFactory;

public class FixedPortRMISocketFactory extends RMISocketFactory {
private static int socketNumber = 60000;
public Socket createSocket(String host, int port) throws IOException {
return new Socket(host, port);
}
public ServerSocket createServerSocket(int port) throws IOException {
if(port == 0) {
socketNumber++;
port = socketNumber;
}
return new ServerSocket(port);
}
}

will use port 60000 for registry and 60001, 60002, ... for
server.
Servlets can communicate via any port. The initial connection is made to the
servlet container on whatever port that happens to be listening on. It may be
80, or 8080 or any other port. The socket is passed to the servlet's service
routine and the servlet can send a reply on that already established socket.
There is no requirement for communication to be HTTP unless you extend
HttpServlet. A GenericServlet can use any protocol (layered over TCP/IP).

Servlets can also open any other socket they wish, including initiating callback
to a client. If you do this in the service method you are likely to get
deadlock if the servlet attempts to initiate a new communication channel with
the client whilst the client is waiting for the servlet to respond to its
initial request. You would have to handle this carefully.

Servlet containers are not written to support long running servlets.
You could also start a background thread in the servlet. The background thread
could open a socket to the client and send data when it was ready. The client
would have to be listening to accept the connection and be able to read the
data.

Much better concept.
But with this method you are at the mercy of the servlet container as it
may decide to unload the servlet if it doesn't received any new service calls.

I think that is only theoretical.
The simplest method is to use blocking calls. The client makes a service request
to the servlet as normal, but the servlet does not return until there is
something to return.

I think a non non waiting servlet and a thread is much better.

With many requests the waiting servlets could lockup the container.
I have no experience of proxies so can't help here.

Piece of cake.

For URLConnection one just set a couple of defines to setup
the proxy server.

With plain sockets one connect to the proxy server and send
the request just with full URL instead of just path.

Arne
 
A

Arne Vajhøj

Roger said:
Resin's Comet seems to just be a long (timewise) request to a servlet.
As far as I can tell the application (Applet, JavaScript, etc) initiates
a HTTP request to the server (let's assume a servlet). The servlet
accepts the request, but instead of just returning an answer it hangs on
to the request/response and sends back data as it becomes available.
With Ajax they seem to be sending <script>...</script> as part of each
response as the browser will parse and execute those as they come
without waiting until the request is completed. See
http://www.caucho.com/resin-3.1/examples/servlet-comet/
Something similar could probably be implemented for applets as well.

But how will that work with many clients ?

Arne
 
Q

Qu0ll

Thanks for the info...
You could also start a background thread in the servlet. The background
thread
could open a socket to the client and send data when it was ready. The
client
would have to be listening to accept the connection and be able to read
the
data. But with this method you are at the mercy of the servlet container
as it
may decide to unload the servlet if it doesn't received any new service
calls.

If I open a socket to the client in a separate thread, how do that thread
know who/where the client is and how does it know when the client is ready
to accept data? And how does the client know when to respond to accept the
socket connection and when to receive data? Sorry for the confusion - this
is all very new to me.

--
And loving it,

-Q
_________________________________________________
(e-mail address removed)
(Replace the "SixFour" with numbers to email me)
 
R

Roger Lindsjö

Arne said:
But how will that work with many clients ?

Probably very badly. I was just commenting on what Comet was and how the
"Push" works and how to apply the same technology to applets.

//Roger Lindsjö
 
N

Nigel Wade

Arne said:
It is possible.

RMISocketFactory.setSocketFactory(new FixedPortRMISocketFactory());
LocateRegistry.createRegistry(60000);

and:

package test.server;

import java.io.IOException;
import java.net.Socket;
import java.net.ServerSocket;
import java.rmi.server.RMISocketFactory;

public class FixedPortRMISocketFactory extends RMISocketFactory {
private static int socketNumber = 60000;
public Socket createSocket(String host, int port) throws IOException {
return new Socket(host, port);
}
public ServerSocket createServerSocket(int port) throws IOException {
if(port == 0) {
socketNumber++;
port = socketNumber;
}
return new ServerSocket(port);
}
}

will use port 60000 for registry and 60001, 60002, ... for
server.


Servlet containers are not written to support long running servlets.

"Long" as in "how long is a piece of string" is a relative term... ;-)
Much better concept.

I have tried this specific method and failed. The thread would run perfectly for
anything between 12 to 14 days, and then die without any indication as to why
it had died. There was no output in any of the Tomcat logs, or the servlet
logs, no stack trace, and I was unable to establish any monitor which would
trap the thread's death. It just vanished without a trace. Needless to say, a
thread which runs for 12 to 14 days and then vanishes is rather hard to debug.
So I changed the design to use blocking calls.

In my case the "long" as discussed above is typically of the order of 10s, and I
use a timeout so there is no issue with the container and long running
servlets. Of course this means the client has to handle the problem of a call
returning with no data. But that's a simple matter of having the thread in the
client which reads the data loop over the call, and re-issue it if the return
status indicates a timeout.
calls.

I think that is only theoretical.
Maybe...


I think a non non waiting servlet and a thread is much better.

It would be if it can be made to work. Besides keeping the thread alive, you
have the problem of the servlet being able to establish a connection back to
the client through whatever firewalls are in the way.
With many requests the waiting servlets could lockup the container.

Yep, all the methods have pros and cons. These need to be weighed up in the
context of how the application will be used in practise. I don't think there is
any "one size fits all" solution to this type of problem.
 
N

Nigel Wade

Qu0ll said:
Thanks for the info...


If I open a socket to the client in a separate thread, how do that thread
know who/where the client is and how does it know when the client is ready
to accept data?

The client has to be listening before it makes the call to the servlet (or you
need some other synchronization method). The client must tell the servlet where
to connect back to, or the client has to use a fixed port. This needs to be
part of the protocol.
And how does the client know when to respond to accept the
socket connection and when to receive data? Sorry for the confusion - this
is all very new to me.

I would expect the client to create a ServerSocket, either on a fixed port or
randomly assigned port. It would need to create a new thread to accept a call
on that Socket and handle the data the servlet thread sends. Then it can then
make a call to the servlet to start the thread, possibly including the port
number for the callback.
 
Q

Qu0ll

The client has to be listening before it makes the call to the servlet (or
you
need some other synchronization method). The client must tell the servlet
where
to connect back to, or the client has to use a fixed port. This needs to
be
part of the protocol.
I would expect the client to create a ServerSocket, either on a fixed port
or
randomly assigned port. It would need to create a new thread to accept a
call
on that Socket and handle the data the servlet thread sends. Then it can
then
make a call to the servlet to start the thread, possibly including the
port
number for the callback.

This may sound like a silly question, but by opening sockets on particular
port(s), aren't we back at square one with respect to firewalls and their
related problems? This is the key thing I am trying to work around.

--
And loving it,

-Q
_________________________________________________
(e-mail address removed)
(Replace the "SixFour" with numbers to email me)
 
L

Lew

Qu0ll said:
This may sound like a silly question, but by opening sockets on
particular port(s), aren't we back at square one with respect to
firewalls and their related problems? This is the key thing I am trying
to work around.

Yes. That's one reason why most client-server protocols eschew client
callbacks, plus it's complicated. Firewalls generally allow return traffic
for outbound clients, but they get finicky about spontaneous inbound traffic.
 
M

Matt Humphrey

Lew said:
Yes. That's one reason why most client-server protocols eschew client
callbacks, plus it's complicated. Firewalls generally allow return
traffic for outbound clients, but they get finicky about spontaneous
inbound traffic.

Where finicky here means that any meaningful firewall will block the
incoming connections by default and NAT routers will completely block the
incoming requests unless forwarding is explicitly allowed.

Matt Humphrey http://www.iviz.com/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top