1

I've been plying with RMI recently and while I managed to make it work on locahost I've been having all sorts of problem when trying to use a remote server. Here's the basic code I'm trying to run:

Server:

public class RmiServer extends UnicastRemoteObject implements RmiServerIntf {
    public static final String MESSAGE = "Hello world";

    public RmiServer() throws RemoteException {
    }

    public String getMessage() {
    return MESSAGE;
    }

    public static void main(String args[]) {
        System.out.println("RMI server started");

        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new RMISecurityManager());
            System.out.println("Security manager installed.");
            } else {
                   System.out.println("Security manager already exists.");
            }

            try {
                    LocateRegistry.createRegistry(1099);
                    System.out.println("java RMI registry created.");
            } catch (RemoteException e) {
                    e.printStackTrace();
            }

            try {
                    RmiServer obj = new RmiServer();

                    Naming.rebind("rmi://localhost/RmiServer", obj);

                    System.out.println("PeerServer bound in registry");
            } catch (Exception e) {
                    e.printStackTrace();
            }
      }
}

Remote class interface:

public interface RmiServerIntf extends Remote {
    public String getMessage() throws RemoteException;
}

Client:

public class RmiClient { 
    RmiServerIntf obj = null; 

    public String getMessage() { 
        try { 
            obj = (RmiServerIntf)Naming.lookup("rmi://54.229.66.xxx/RmiServer");
            return obj.getMessage(); 
        } catch (Exception e) { 
            e.printStackTrace(); 
            return e.getMessage();
        } 
    } 

    public static void main(String args[]) {
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new RMISecurityManager());
        }

        RmiClient cli = new RmiClient();

        System.out.println(cli.getMessage());
    }
}

rmi.policy file:

grant {
permission java.security.AllPermission;
};

I compiled the classes and created a stub for the server. Then I placed client, stub, interface and policy on my machine and server, stub, interface and policy on the remote machine. The remote server being a Linux machine I made all the files executable. I also added a rule on the local firewall allowing port 1099, and opened all ports on the remote machine

After this I navigated to the server's directory on the remote machine and inserted the following command:

java -Djava.security.policy=rmi.policy RmiServer

This didn't give me problems so I went back to the local machine and entered

java -Djava.security.policy=rmi.policy RmiClient

I wait, and wait and I get the error message:

Connection refused to host: 172.31.xx.xx; nested exception is: java.net.ConnectException: Connection timed out: connect 

I've been fighting with these connection errors all day yesterday and this is as far as I got. I'm sure there's only one very small thing I'm still doing wrong but I just can't find what it is.

spacitron
  • 2,095
  • 7
  • 30
  • 39
  • Can you connect to any port on your remote machine using e.g. telnet? –  Jul 16 '13 at 16:25
  • Yes, I have no problem with other types of connections. I used port 22, 80 or 11111 (JPPF) with no problem. – spacitron Jul 16 '13 at 16:30
  • Your client code has a different ip address from the "Connection refused" message, so the following may be of help: http://stackoverflow.com/questions/3071376/what-port-is-used-by-java-rmi-connection –  Jul 16 '13 at 16:36

2 Answers2

1

This may not solve your problem, but I've had similar issues with JPPF (via Java RMI) on Linux. The solution was to ensure that the ephemeral port range on the Client-side machine covered only ports that were allowable by the Client-side's local firewall. E.g., if your firewall allows ports 48000 to 64000 to be connected to by an external machine, ensure that your ephemeral port range also falls within 48000 to 64000. Give that a try and let us know what happens.

CodeBlind
  • 4,519
  • 1
  • 24
  • 36
  • +1 but the Registry doesn't 'hand off connections' at all. It's not invoked in the connect phase. What really happens is that unless you specify a port when exporting your remote object, it *listens* at an ephemeral port. – user207421 Jul 16 '13 at 22:13
  • I'm not talking specifically about the Registry, I'm talking about the underlying network mechanisms used to serve that Registry up. Under the hood, RMI uses `ServerSocket` and `Socket`. `ServerSocket` most definitely listens on a specific port, and after an initial handshake with the client, hands off all subsequent communication with that client to a `Socket` that listens on a completely different ephemeral port number, regardless of what port number you chose to have your `ServerSocket` listen on. – CodeBlind Jul 16 '13 at 23:03
  • You are mistaken. ServerSocket returns Sockets whose local port number is the *same* as the listening port number. Therefore if you export an RMI object on a fixed port, all connections to that object will use that port. The reason ephemeral poets appear in RMI is because of not providing a non-zero port number when exporting, e.g. via super(int port). – user207421 Jul 17 '13 at 22:39
  • My mistake indeed. My first exposure to RMI was on a project that used custom ServerSocket and Socket factories that behaved in the "hand-off" manner I described - we did this to make it more difficult for an adversary to hijack a specific client connection - but it's been awhile, so I mistook this for the default RMI behavior. – CodeBlind Jul 17 '13 at 23:00
  • I don't see how that is even possible, unless you used extra listening sockets on ephemeral ports. I suggest your recollection is also mistaken. I also suggest you fix your answer. – user207421 Jul 17 '13 at 23:19
  • " ...unless you used extra listening sockets on ephemeral ports" - that's *exactly* how it was implemented. Answer fixed. – CodeBlind Jul 17 '13 at 23:48
-3
System.setProperty("java.rmi.server.hostname","10.0.3.73");

Please use the above statements in your RMIServer side code, and try and connect from remote client again. It worked for me

DimaSan
  • 12,264
  • 11
  • 65
  • 75
  • 3
    It worked for you on that IP address because that is one of your IP addresses. Nothing about it that is guaranteed to work for everybody. – user207421 Dec 16 '16 at 05:10