Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
816 views
in Technique[技术] by (71.8m points)

java - RMI lookup works but method invocation not

UPDATE:

The problem is, that i'm using a kind of 2-way connection.

On client side, this works:

String a = this.lobby.getMsg();

and this not:

this.lobby.login((Player)UnicastRemoteObject.exportObject(player, 0));

and ideas?



I'm working on a java application which uses RMI for network communication.

On one computer everythings works good, but if i try to run it via the internet i ran into problems.

It seems, that the client is able to retreive the registry from the server and to lookup the lobby-object. But if the client tries to call the login method of the lobby object via rmi, it takes very long time and i receive the following exception:

Strange thing is, that there is the wrong ip(the client ip) mentioned in this exception. And if I run a client on the same machine as the server, it works perfectly.

java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
    java.rmi.ConnectException: Connection refused to host: <client ip(should be server ip?)>; nested exception is: 
    java.net.ConnectException: Die Wartezeit für die Verbindung ist abgelaufen (=time out)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:353)
    at sun.rmi.transport.Transport$1.run(Transport.java:177)
    at sun.rmi.transport.Transport$1.run(Transport.java:174)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:553)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:808)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:667)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
    at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:273)
    at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:251)
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:160)
    at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:194)
    at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:148)
    at $Proxy0.einloggen(Unknown Source)
    at Client.login(Client.java:64)

Here is the relevant code:

My server class:

    public static final int RMI_PORT = 55555;
    public static final String SERVER_IP = "xyz.com";

    /**
     * Startet Spielserver
     * 
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("Server starten..");

        System.setProperty("java.rmi.server.hostname", SERVER_IP);
        try {
            if (System.getSecurityManager() == null) {
                System.setSecurityManager(new RMISecurityManager());
            }

            Registry registry = LocateRegistry.getRegistry(SERVER_IP, RMI_PORT);

            Lobby lobby = new LobbyImpl();
            UnicastRemoteObject.exportObject(lobby, 0);
            registry.bind("Lobby", lobby);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (AlreadyBoundException e) {
            e.printStackTrace();
        }
    }

Client class:

public Client() {
        try {
            Registry registry = LocateRegistry.getRegistry("xyz.com", Server.RMI_PORT);
            lobby = (Lobby) registry.lookup("Lobby");
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (NotBoundException e) {
            e.printStackTrace();
        }
        this.gui = new GUI(this);
    }

    public void login(String name) throws RemoteException {
        Player player = new Player(name);
        this.lobby.login((Player)UnicastRemoteObject.exportObject(player, 0));  
    }

Client startscript:

#!/bin/bash
SCRIPTDIR=$(dirname $0)
java -classpath $SCRIPTDIR/bin Client

Server startscript:

#!/bin/bash
SCRIPTDIR=$(dirname $0)

cd ${SCRIPTDIR}/bin
rmiregistry 55555 &
cd - 
java -classpath $SCRIPTDIR/bin -Djava.security.policy=$SCRIPTDIR/src/server.policy -Djava.rmi.server.codebase=file:$SCRIPTDIR/bin/ Server
killall rmiregistry

and last but not least my first (test) policy file:

grant {
    permission java.security.AllPermission;
};

what could be the problem?

regards

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You need to look at item A.1 of the RMI FAQ on the RMI home page. The problem here is that the wrong IP address is being embedded into the remote stub. So the lookup works, because you are specifying the target IP address yourself in the client, but when you execute the remote method you are relying on the IP address in the stub, which is wrong. The solution is either to correct your /etc/hosts file or to set the system property java.rmi.server.hostname at the server JVM.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...