RMI查找有效,但方法调用无效 [英] RMI lookup works but method invocation not

查看:57
本文介绍了RMI查找有效,但方法调用无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题是,我正在使用一种2通连接.

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

在客户端,这有效:

String a = this.lobby.getMsg();

而不是:

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

和想法?

我正在开发一个使用RMI进行网络通信的Java应用程序.

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.

看来,客户端能够从服务器检索注册表并查找游说对象.但是,如果客户端尝试通过rmi调用大厅对象的登录方法,则会花费很长时间,而且我会收到以下异常:

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:

奇怪的是,此异常中提到了错误的ip(客户端ip).而且,如果我在与服务器相同的计算机上运行客户端,那么它可以完美运行.

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)


以下是相关代码:

我的服务器类:

    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();
        }
    }

客户端类:

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));  
    }

客户端启动脚本:

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

服务器启动脚本:

#!/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;
};

可能是什么问题?

致谢

推荐答案

您需要在RMI主页上查看RMI常见问题解答的项目A.1.这里的问题是错误的IP地址被嵌入到远程存根中.这样查找就可以了,因为您是在客户端中自己指定目标IP地址,但是执行远程方法时却依赖于存根中的IP地址,这是错误的.解决方案是更正/etc/hosts文件或在服务器JVM上设置系统属性java.rmi.server.hostname.

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.

这篇关于RMI查找有效,但方法调用无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆