views:

136

answers:

1

I've been using RMI in this project for a while. I've gotten the client program to connect (amongst other things) to the server when running it over my LAN, however when running it over the internet I'm running into the following exception:

java.rmi.ConnectException: Connection refused to host: (private IP of host machine); 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.invoke(Unknown Source)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unknown Source)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source)
at $Proxy1.ping(Unknown Source)
at client.Launcher$PingLabel.runPing(Launcher.java:366)
at client.Launcher$PingLabel.<init>(Launcher.java:353)
at client.Launcher.setupContentPane(Launcher.java:112)
at client.Launcher.<init>(Launcher.java:99)
at client.Launcher.main(Launcher.java:59)

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)
... 12 more

This error is remeniscent of my early implementation of RMI and I can obtain the error verbatum if I run the client locally without the server program running as well. To me Connection Timed Out means a problem with the server's response.

Here's the client initiation:

public static void main(String[] args)
{
    try
    {
        String host = "<WAN IP>";
        Registry registry = LocateRegistry.getRegistry(host, 1099);
        Login lstub = (Login) registry.lookup("Login Server");
        Information istub = (Information) registry.lookup("Game Server");
        new Launcher(istub, lstub);

    }
    catch (RemoteException e)
    {
        System.err.println("Client exception: " + e.toString());
        e.printStackTrace();
    }
    catch (NotBoundException e)
    {
        System.err.println("Client exception: " + e.toString());
        e.printStackTrace();
    }
}

Interestingly enough no Remote Exception is thrown here. Here's the server initiation:

public static void main(String args[])
{
    try
    {
        GameServer gobj = new GameServer();
        Information gstub = (Information) UnicastRemoteObject.exportObject(
                gobj, 1099);
        Registry registry = LocateRegistry.createRegistry(1099);
        registry.bind("Game Server", gstub);

        LoginServer lobj = new LoginServer(gobj);
        Login lstub = (Login) UnicastRemoteObject.exportObject(lobj, 7099);

        // Bind the remote object's stub in the registry
        registry.bind("Login Server", lstub);

        System.out.println("Server ready");
    }
    catch (Exception e)
    {
        System.err.println("Server exception: " + e.toString());
        e.printStackTrace();
    }
}

Bad practice with the catch(Exception e) I know but bear with me.

Up to this stage I know it works fine over the LAN, here's where the exception occurs over the WAN and is the first place a method in the server is called:

private class PingLabel extends JLabel
{
    private static final long serialVersionUID = 1L;

    public PingLabel()
    {
        super("");
        runPing();
    }

    public void setText(String text)
    {
        super.setText("Ping: " + text + "ms");
    }

    public void runPing()
    {
        try
        {
            PingThread pt = new PingThread();
            gameServer.ping();
            pt.setRecieved(true);
            setText("" + pt.getTime());
        }
        catch (RemoteException e)
        {
            e.printStackTrace();
        }
    }
}

That's a label placed on the launcher as a ping test. the method ping(), in gameserver does nothing, as in is a null method.

It's worth noting also that ports 1099 and 7099 are forwarded to the server machine (which should be obvious from the stack trace).

Can anyone see anyting I'm missing/doing wrong? If you need any more information just ask.

EDIT: I'm practically certain the problem has nothing to do with my router settings. When disabling my port forwarding settings I get a slightly different error:

Client exception: java.rmi.ConnectException: Connection refused to host: (-WAN IP NOT LOCAL IP-);

but it appears both on the machine locally connected to the server and on the remote machine.

In addition, I got it to work seamlessly when connecting the server straight tho the modem (cutting out the router. I can only conclude the problem is in my router's settings but can't see where (I've checked and double checked the port forwarding page). That's the only answer i can come up with.

+1  A: 

Are you using NAT (Network Address Translation)? This is the typical case if your LAN uses non-routable address behind a router (like 10.x or 192.169.x etc).

If this is the case, you need to specify the public IP of the server with following option,

-Djava.rmi.server.hostname=host_name_or_public_ip
ZZ Coder
I've not got access to my remote machine atm so I can't test it right now, but surely that's the point of the 'String host = "<WAN IP>"; Registry registry = LocateRegistry.getRegistry(host, 1099);'code isn't it?
Koe
If your machine is multi-homed, you can listen on the WAN IP. Otherwise, you need to listen on the local IP because the machine doesn't even own the WAN IP (it belongs to the router).
ZZ Coder
'String host = "<WAN IP>"; Registry registry = LocateRegistry.getRegistry(host, 1099);' is in the client, it tells the client to get the registry from the server's WAN IP on a port the server is listening to (or that's my understanding of it).So I'd have thought the -Djava.rmi... option would be redundant.
Koe
Also, tried that option but it didn't work, spat an exception that the hostname wasn't recognised.
Koe
sorry, turns out this worked perfectly, I set the property in the client (System.setProperty("java.rmi.server.hostname", "(host IP)")). thanks.
Koe