Java 我必须如何配置 RMI 环境才能在“真实”网络中使用它?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1167551/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 00:27:28  来源:igfitidea点击:

How do I have to configure a RMI environment so that I'm able to use it in a "real" network?

javanetworkingpropertiesrmi

提问by Markus

Because I didn't want to implement a communication protocol for my client-server based application, I implemented a RMI client and a RMI server on both sides for the information exchange between the two components.

因为我不想为基于客户端-服务器的应用程序实现通信协议,所以我在两侧实现了一个 RMI 客户端和一个 RMI 服务器,用于两个组件之间的信息交换。

If I try to use my application by starting the two components on the same machine, everything is working fine. But if I split the components to two different computers (Kubuntu 9.04 within as a virtual machine within an Windows 7 RC environment with disabled firewall and a native Ubuntu 9.04 environment), it seems like the RMI client is not able to execute the methods which are defined on the server side. (Every functions call leads to a RMI exception.)

如果我尝试通过在同一台机器上启动两个组件来使用我的应用程序,一切正常。但是,如果我将组件拆分到两台不同的计算机(Kubuntu 9.04 作为 Windows 7 RC 环境中的虚拟机,禁用防火墙和本机 Ubuntu 9.04 环境),似乎 RMI 客户端无法执行这些方法在服务器端定义。(每个函数调用都会导致 RMI 异常。)

Currently I only set the system property "java.rmi.server.hostname" on both sides to the network interface which should be used for the data exchange and registered the default port for the communication with rmi daemon (?) rmid.

目前我只将双方的系统属性“java.rmi.server.hostname”设置为应该用于数据交换的网络接口,并注册了与rmi守护进程(?)rmid通信的默认端口。

Does somebody has an idea what might be going wrong? Do I have to set some other parameters like "java.rmi.server.codebase" (http://java.sun.com/j2se/1.4.2/docs/guide/rmi/javarmiproperties.html) to be able to use the RMI functionality within my application?

有人知道可能会出什么问题吗?我是否必须设置一些其他参数,如“java.rmi.server.codebase”(http://java.sun.com/j2se/1.4.2/docs/guide/rmi/javarmiproperties.html)才能使用我的应用程序中的 RMI 功能?

Edit: Okay, here is some additional information for you:

编辑:好的,这里有一些额外的信息给你:

In the initialization phase my client tries to establish a connection to the RMI server of server component, which was initialized using the following two methods:

在初始化阶段,我的客户端尝试与服务器组件的 RMI 服务器建立连接,该服务器使用以下两种方法进行初始化:

private void initialize()
{
    // set ip address of rmi server
    System.setProperty("java.rmi.server.hostname", ipAddress);

    // try to register rmi server
    try
    {
        LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
    }
    catch (Exception e)
    {
        // ignore
    }
}

public void start()
{
    System.out.print("starting master control RMI server ...");

    try
    {
        Naming.rebind("MasterControl", this);
    }
    catch (Exception e)
    {
        System.out.println("error: could not initialize master control RMI server");
        System.exit(1);
    }

    // set running flag
    isRunning = true;

    System.out.println(" done");
}

"ipAddress" is here the ip address of the network interface of the server component.

“ipAddress”在这里是服务器组件的网络接口的 ip 地址。

The method which is used by the client component to establish the connection looks like this:

客户端组件用于建立连接的方法如下所示:

    public void connect()
{
    // build connection url
    String url = "rmi://" + masterControlIpAddress + "/MasterControl";

    System.out.println(url);

    System.out.print("connecting to master control ...");

    // try to connect to master control server
    while (connection == null)
    {
        try
        {
            connection = (MasterControlInterface) Naming.lookup(url);
            id = connection.register(localIpAddress);
        }
        catch (Exception e)
        {
            // ignore
        }

        if (connection == null)
        {
            try
            {
                Thread.sleep(100);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }

    System.out.println(" done");
}

As you can see my client calls a function to register the connection at the server:

如您所见,我的客户端调用了一个函数来在服务器上注册连接:

@Override
public int register(String ipAddress) throws RemoteException
{
    // add connection to registrationHandler
    masterControl.registrationHandler.addConnection(ipAddress);

    // log
    int connectionCount = masterControl.registrationHandler.getConnectionCount();
    System.out.println("slave control (" + ipAddress + ") instance has been registered at the master control server under the following id: " + connectionCount);

    return connectionCount;
}

If I run my program using a real network connection, the text "slave control ..." is not displayed on the server side. Therefore I'm not sure, if the function is really called by the client component.

如果我使用真实的网络连接运行我的程序,则服务器端不会显示文本“slave control ...”。因此,我不确定该函数是否真的由客户端组件调用。

After the client component is intialized it tries to notify the server component by calling the following method using it's RMI connection to the server:

客户端组件初始化后,它会尝试通过使用它与服务器的 RMI 连接调用以下方法来通知服务器组件:

public void sendInitializationDone()
{
    try
    {
        connection.initializationDone();
    }
    catch (RemoteException e)
    {
        System.out.println("error: could not send 'initializationDone' message to master control");
        System.out.println(e);
        System.exit(1);
    }
}

to set a flag on the server side.

在服务器端设置一个标志。

The error occures inside this function on the client side:

错误发生在客户端的这个函数中:

java.rmi.ConnectException: Connection refused to host 127.0.1.1; nested exception is: java.net.ConnectException: Connection refused.

java.rmi.ConnectException:连接拒绝托管 127.0.1.1;嵌套异常是:java.net.ConnectException:连接被拒绝。

I have no idea why the host is here 127.0.1.1 ...

我不知道为什么主机在这里 127.0.1.1 ...

@nos

@nos

Of course, I disabled the windows firewall and the protection mechanismn of Kaspersky Internet Security. I don't think that there is a running firewall in my Kubuntu. In generell it is possible to establish a connection, because I already used scp to copy my program to the other machine.

当然,我关闭了windows防火墙和卡巴斯基安全软件的保护机制。我认为我的 Kubuntu 中没有正在运行的防火墙。一般来说,可以建立连接,因为我已经使用 scp 将我的程序复制到另一台机器上。

Edit2:

编辑2:

Mhhh, after setting the entry in /etc/hosts which refers to the machine to the ip address of the machine it seems to work, but don't really understand why it does ...

嗯,在将 /etc/hosts 中的条目设置为机器的 IP 地址后,它似乎可以工作,但并不真正理解为什么会这样......

BR,

BR,

Markus

马库斯

采纳答案by Robert Munteanu

You need to add an entry to the hosts fileof the machines containing an entry of the form

您需要hosts file在包含表单条目的机器中添加一个条目

machinename    privateip

e.g.

例如

virtualmachine    192.168.1.16

This will prevent RMI from sending the localhosthost name as a 'call me back' address.

这将阻止 RMI 将localhost主机名作为“回拨”地址发送。

To test this approach, run the following code before and after performing the change.

要测试此方法,请在执行更改之前和之后运行以下代码。

System.out.println(java.net.InetAddress.getLocalHost());

It should output a local address before the changes and a non-local address after the changes.

修改前输出本地地址,修改后输出非本地地址。

回答by theoverture

Using different versions of the JDK on each server could cause this problem.

在每台服务器上使用不同版本的 JDK 可能会导致此问题。

Use the java -version command to make sure that you are using the same version of the jre.

使用 java -version 命令确保您使用的是相同版本的 jre。