Search code examples
javarmi

Can't use RMI remote methods


cant fix this for 3 days. RMI works correctly with localhost or 192.168.* on 1 or 2 PCs,but remote clients cant use remote methods. Starting rmiregisry,then binding service with Naming.rebind()

Registry IS CREATING successfuly,i can get list of binded services,but i cant even use any method.

Searching remote service with

Naming.lookup("rmi://host_ip:1099/qwe). 
or
Registry reg = LocateRegistry.getRegistry("host_ip",server);
reg.lookup("qwe")

Client finds the object but cant use it`s methods.

Here is the code: Server.java:

public class Server extends UnicastRemoteObject{

protected Server() throws RemoteException {
}

public static void main(String[] args) throws InterruptedException, RemoteException {
    ServiceServerImpl server = new ServiceServerImpl();
    try {
        System.setProperty("java.rmi.server.hostname", "host_ip");
        Naming.rebind("/qwe", server);
        Arrays.asList(Naming.list("rmi://localhost")).forEach(System.out::println);
        System.out.println(System.getProperty("java.rmi.server.hostname"));
    } catch (Exception e) {
        e.printStackTrace();
    }
    server.startServer();
}
}

ServiceServer.java:

public interface ServiceServer extends Remote{
String[] getLoginsList() throws RemoteException;
void addLogin(String login) throws RemoteException;
void removeLogin(String login) throws RemoteException;
boolean canConnect(String login) throws RemoteException;
void setConnected(String login) throws RemoteException;
void setDisconnected(String login) throws RemoteException;
}

ServiceServerImpl.java(if needed):

public class ServiceServerImpl extends UnicastRemoteObject implements ServiceServer {
private ServerSocket socketListener;
private Socket clientSock;
private volatile List<ClientHandler> threadsList = new ArrayList<ClientHandler>();
private volatile Map<String, Boolean> logins = new HashMap<String,Boolean>();
// private Timer timer;

public ServiceServerImpl() throws RemoteException {
}

public void startServer() {
    // startTimer();
    try {
        socketListener = new ServerSocket(5001);
        System.out.println("server up...");
        while (true) {
            clientSock = null;
            while (clientSock == null)
                clientSock = socketListener.accept();
            ClientHandler curClientHandler = new ClientHandler(clientSock, this);
            threadsList.add(curClientHandler);
            System.out.println("user connected: " + clientSock.getInetAddress());
        }
    } catch (Exception e) {
        System.err.println("Socket exception");
        e.printStackTrace();
    }
}

public synchronized void removeUserThread(ClientHandler handler) {
    try {
        threadsList.remove(handler);
    } catch (NullPointerException e) {
    }
    System.out.println("- 1");
}

@Override
public void setConnected(String login){
    logins.put(login,true);
}

@Override
public void setDisconnected(String login){
    logins.put(login,false);
}

@Override
public boolean canConnect(String login) throws RemoteException{
    return logins.keySet().contains(login)&& (!logins.get(login));
}

@Override
public String[] getLoginsList() throws RemoteException {
    return this.logins.keySet().toArray(new String[this.logins.size()]);
}

@Override
public void addLogin(String login) throws RemoteException {
    logins.put(login, false);
    System.out.println("added");
}

@Override
public void removeLogin(String login) throws RemoteException {
    logins.remove(login);
}


public Map<String, Boolean> getLogins() {
    return logins;
}

public Set<String> getAllowedLogins() {
    return logins.keySet();
}

public List<ClientHandler> getThreadsList() {
    return threadsList;
}
}

Im starting rmiregistry with cmd or with eclipse,then starting the Sever. It starts correctly and I cant connect with localhost or 192.168.0.* BUT IT DOESNT WORK for remote clients Tried to use .policy files- still doesnt work

i get next Error code:

Exception in thread "main" java.rmi.ConnectException: Connection refused to host: 192.168.0.83; 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 com.sun.proxy.$Proxy0.canConnect(Unknown Source)
at server.Main.main(Main.java:16)
Caused by: java.net.ConnectException: Connection timed out: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
at java.net.AbstractPlainSocketImpl.connect(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)
... 8 more

Help please


Solution

  • You need to:

    1. Set java.rmi.server.hostname to the external IP address of your system, that is to say the public IP address of your router.
    2. Export your remote object(s) on a fixed port number, via super(port).
    3. Arrange port forwarding in your router for those ports and port 1099.

    How to do (3) is router-dependent and off topic.