Re: RMI & connection refused
Duane Evenson wrote:
On Sun, 02 Aug 2009 13:39:01 +0100, Tom Anderson wrote:
On Sat, 1 Aug 2009, Duane Evenson wrote:
Here's my commands:
rmiregistry &
java -Djava.security.policy=policy RMIServer localhost 1099 &
java -Djava.security.policy=policy RMIClient localhost 1099
The problem is with the next command from a remote host:
java -Djava.security.policy=policy RMIClient adam 1099
java.rmi.ConnectException: Connection refused to host: 127.0.0.1; nested
exception is:
java.net.ConnectException: Connection refused
Why is it connecting to 127.0.0.1? That's the local loopback interface -
you know about that, right? If the client and server are on different
machines, that doesn't seem like a totally likely to work thing to do.
What's your /etc/hosts look like? What to you get if you do 'ping adam'?
A simple but good diagnostic tool in situations like this is telnet. On
the client machine, telnet to port 1099 on the server machine. If you
manage to make a connection, you know that there's nothing wrong at the
network level, and any problem must be in the program. If you can't make a
connection, you know there's trouble with the network - firewalls, DNS,
routing, something like that.
tom
I assume that reference to 127.0.0.1 isn't important in tracing out the
problem.
It is very relevant. It's the host your client is trying to connect to.
It is just how the registry refers to the server --
The Naming.list() call to the rmiregistry returns the list of registered RMI
servers prefixed by the interface on which the request was made. If the client
makes a request to the rmiregistry on host 1.2.3.4 to get a list of RMI servers
using Naming.list("//1.2.3.4/") then the list of RMI servers returned by would
be //1.2.3.4:1099/RMIserver1, //1.2.3.4:1099/RMIserver2 etc. The registry list
includes the registry host, but not the server IP.
after all
they are the only two who are on the same server, if the client knows the
IP of the registry, it knows the IP of the server.
Not at all. There may be only one rmiregistry for the subnet, but there may be
several RMI servers each registering with that registry. The rmiregistry lookup
(e.g. Naming.lookup("//1.2.3.4:1099/RMIserver1")) should return a Remote object
already connected to the RMI server in question. The RMI server may or may not
be on host 1.2.3.4.
I think I know the problem here. I assumed the server would keep the port
open with which it communicate with the registry. Then, at the network
level, would use "Related" state to switch to communicating with the
client. Further reading of the Javadoc for UnicastRemoteObject finds
that the server listens on a second, random port for a client. I don't
know how most firewalls are supposed to handle this, but I used a
different constructor that specified a fixed, non-firewalled port.
That is one of the joys of this type of networking. Usually you have to open all
high ports (1024 up) incoming from the client. I imagine that RMI has any built
in way of opening ports (it would hardly be portable, and Java should be
portable). Offhand I can't remember whether RMI allows a server to listen on a
specific port and then register that port with rmiregistry. If it did at least
you'd only have to open one port.
Now I'm getting another problem -- when I execute the server, I'm getting
errors, but the server still continues (hangs like it should) but nothing
is registered with the RMI name server.
I'm getting:
Server exception: java.rmi.ServerException: RemoteException occurred in
server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested
exception is: java.lang.ClassNotFoundException: dbServer.Server
java.rmi.ServerException: RemoteException occurred in server thread;
nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested
exception is: java.lang.ClassNotFoundException: dbServer.Server at
sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:385)
at
sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:240)
at sun.rmi.transport.Transport$1.run(Transport.java:153) at
java.security.AccessController.doPrivileged(Native Method) at
sun.rmi.transport.Transport.serviceCall(Transport.java:149)
...
IIRC this happens if the rmiregisty, RMI server and/or the RMI client are using
different versions of the same class, one of the classes which needs to be
marshalled/unmarshalled as a RMI call parameter or return value. Marshalling
relies on the serialVersionUID to ensure the class is consistent on both client
and server. Check the versions of the classes used in each instance.
Recompiling (unless you have correctly used your own serialVersionUID) will
result in a new UID being assigned to the class and that will prevent
marshalling if a different version of the class is used on the client/server.
If you recompile on the server then you need to propagate the new class files
to the rmiregistry and the client.
Using the -verbose flag, I can see that dbServer.Server (which is the
interface for the server is loading OK:
...
[Loaded java.security.cert.Certificate
from /usr/local/jdk1.5.0_06/jre/lib/rt.ja
r]
[Loaded java.rmi.Remote from /usr/local/jdk1.5.0_06/jre/lib/rt.jar]
[Loaded dbServer.Server from file:/home/duanee/]
[Loaded java.rmi.server.RemoteObject
from /usr/local/jdk1.5.0_06/jre/lib/rt.jar]
[Loaded java.rmi.server.RemoteServer
from /usr/local/jdk1.5.0_06/jre/lib/rt.jar]
[Loaded java.rmi.server.UnicastRemoteObject
from /usr/local/jdk1.5.0_06/jre/lib/
rt.jar]
[Loaded dbServer.ServerImpl from file:/home/duanee/]
[Loaded java.io.IOException from /usr/local/jdk1.5.0_06/jre/lib/rt.jar]
[Loaded java.rmi.RemoteException from /usr/local/jdk1.5.0_06/jre/lib/rt.jar]
[Loaded java.sql.SQLException from /usr/local/jdk1.5.0_06/jre/lib/rt.jar]
[...
I'm running Java 1.5 so I don't need stubs. Still, I tried precompiling
them with rmic, but the problem persists.
--
Nigel Wade