1

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

Panup Pong
  • 1,871
  • 2
  • 22
  • 44

3 Answers3

1

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.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • if i use super(port) in the interface impl and it doesnt work with it(port already in use when running) – shaldnikita Feb 12 '17 at 22:20
  • So, err, use another port? And if there is relevant matter missing from your question you should fix that. – user207421 Feb 12 '17 at 22:25
  • If this was all really 'already done, mate', you wouldn't have the problem, and you wouldn't have just discovered that you have a port conflict. – user207421 Feb 12 '17 at 22:41
  • You should have no problem at all any more, as you should no longer be attempting to connect to 192.168.*. – user207421 Feb 13 '17 at 02:25
  • Ok i understand now.So u should use super(port_name) in the interface_imlp`s constructor and then start the server using THAT(port_name) port?Or should i use super(5005) and then start Registry using 1099 default port? – shaldnikita Feb 13 '17 at 16:42
  • @shaldnikita Your question appears to be answered by my point (3). – user207421 Dec 13 '18 at 08:14
  • @shaldnikita You should use whatever fixed ports you have arranged port forwarding for, and you should arrange port forwarding for whatever fixed ports you are planning to use. You can use the single Registry port for everything if and only if you export all your remote objects including the Registry from the same JVM, and they all use no socket factories, or the same socket factories, or socket factories that are `equals()`-compatible. – user207421 Dec 19 '18 at 04:02
0

From your description, you have a general network connection problem, which is not specific to RMI. My advice is to put aside RMI and work with netcat or some other generic client/server implementation until you get the connection stuff sorted out, and then go back to RMI.

My guess is that there are at least two layers of security that you have to cross. One is that the PC which is running the RMI server is blocking connections on all ports or maybe all but a small list of ports. You will first need to open port 1099 (which is the default RMI port, of course you can choose something else) on the RMI host. If you do that, you should be able to connect to the RMI host from another host on the same local network (i.e. on the same subnetwork 192.168.something.something).

If you get that connection working, the next bridge to cross is that the router on the local network is probably blocking traffic from outside the local network. Bear in mind that this is an important security measure. My advice is to avoid opening a connection directly to the RMI host from the outside, since that is a security risk. Instead try to set up an SSH tunnel and then use the tunnel to carry the connection from outside to the RMI host. SSH tunneling isn't too complicated; a web search should turn up an explanation.

Clients might also be blocking outbound connections to port 1099; you will have to enable those connections, or use SSH tunneling to avoid the problem.

In the early days (circa 1999) I set up a global network (well, about 4 sites) which communicated via RMI. There was no obstacle with network security at the time. So it is certainly possible to communicate remotely via RMI, you just have to get through the firewalls. Good luck and have fun.

Robert Dodier
  • 16,905
  • 2
  • 31
  • 48
  • its ok with the connection.Client finds remote object but cant use it`s methods – shaldnikita Feb 12 '17 at 21:47
  • @shaldnikita It's OK with the connection to the Registry. It isn't OK with the connection to the remote object. – user207421 Feb 12 '17 at 22:14
  • @EJP it connects to the remote registry but cant invoke any method – shaldnikita Feb 12 '17 at 22:20
  • @shaldnikita OK, thanks for the info. RMI uses randomly-allocated ports to communicate between clients and remote objects. So even if you are able to connect to port 1099, you may not be able to connect to the random port. There's more info here: http://stackoverflow.com/questions/3071376/what-port-is-used-by-java-rmi-connection – Robert Dodier Feb 12 '17 at 23:02
  • @shaldnikita If you are working on a Linux system, try `netstat` to see what ports are opened for listening. (`netstat` might be available on other systems too.) – Robert Dodier Feb 12 '17 at 23:04
  • @shaldnikita You're just repeating yourself. I'm telling you *why.* – user207421 Feb 13 '17 at 00:24
  • @RobertDodier It uses randomly-allocated ports unless you specify one yourself, which he needs to do. – user207421 Feb 13 '17 at 00:25
0

192.168.X.X is a private/Class C IP address which identifies your machine on your local network. To expose your services to others/internet users, you will need to configure port forwarding on your router. It also helps to use a free dynamic DNS service like NoIP to ensure your machine remains reachable even after restarts (given that your ISP will almost always assign you a new dynamic public IP address).

Once you have that sorted out, ensure that you are not binding your RMI server to localhost or 127.0.0.1 but to 0.0.0.0.

Sanjay T. Sharma
  • 22,857
  • 4
  • 59
  • 71
  • how can i ensure? – shaldnikita Feb 12 '17 at 20:39
  • @shaldnikita You aren't binding to 127.0.0.1, and you can't without using an `RMIServerSocketFactory`. It's irrelevant. – user207421 Feb 12 '17 at 22:29
  • @shaldnikita: Personal firewalls are notorious (and rightly so) for blocking all incoming unknown external traffic. Are you sure your server machine has proper rules in place? If you are using a firewall+antivirus, ensure that you allow all incoming traffic on the RMI server port. – Sanjay T. Sharma Feb 12 '17 at 22:51
  • @SanjayT.Sharma i opened needed ports via router and firewall – shaldnikita Feb 12 '17 at 22:54