因为我不想为基于客户端-服务器的应用程序实现通信协议(protocol),所以我在两侧实现了 RMI 客户端和 RMI 服务器,用于两个组件之间的信息交换。
如果我尝试通过在同一台计算机上启动两个组件来使用我的应用程序,则一切正常。但是,如果我将组件拆分到两台不同的计算机(Kubuntu 9.04 作为 Windows 7 RC 环境中的虚拟机,禁用防火墙和 native Ubuntu 9.04 环境),则 RMI 客户端似乎无法执行以下方法:在服务器端定义。 (每个函数调用都会导致 RMI 异常。)
目前我只将两侧的系统属性“java.rmi.server.hostname”设置为用于数据交换的网络接口(interface),并注册了与rmi守护进程(?)rmid通信的默认端口。
有人知道可能出了什么问题吗?我是否必须设置一些其他参数,例如“java.rmi.server.codebase”( http://java.sun.com/j2se/1.4.2/docs/guide/rmi/javarmiproperties.html ) 才能在我的应用程序中使用 RMI 功能?
编辑:好的,这里有一些附加信息供您引用:
在初始化阶段,我的客户端尝试与服务器组件的 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”是服务器组件网络接口(interface)的IP地址。
客户端组件用来建立连接的方法如下所示:
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");
}
正如您所看到的,我的客户端调用了一个函数来在服务器上注册连接:
@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;
}
如果我使用真实的网络连接运行我的程序,文本“从属控制...”不会显示在服务器端。因此我不确定该函数是否真的由客户端组件调用。
客户端组件初始化后,它会尝试使用与服务器的 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);
}
}
在服务器端设置标志。
客户端此函数内发生错误:
java.rmi.ConnectException:连接拒绝主机 127.0.1.1;嵌套异常是:java.net.ConnectException:连接被拒绝。
我不知道为什么主机在这里 127.0.1.1 ...
@nos
当然,我禁用了Windows防火墙和卡巴斯基安全软件的保护机制。我认为我的 Kubuntu 中没有运行防火墙。一般来说,可以建立连接,因为我已经使用 scp 将程序复制到另一台机器。
编辑2:
嗯,在/etc/hosts 中设置将机器引用到机器的 IP 地址的条目后,它似乎可以工作,但不太明白为什么会这样......
BR,
马库斯
最佳答案
您需要向包含以下形式条目的计算机的 hosts 文件
添加一个条目
machinename privateip
例如
virtualmachine 192.168.1.16
这将阻止 RMI 将 localhost
主机名作为“回电”地址发送。
要测试此方法,请在执行更改之前和之后运行以下代码。
System.out.println(java.net.InetAddress.getLocalHost());
它应该输出更改前的本地地址和更改后的非本地地址。
关于java - 我必须如何配置 RMI 环境才能在 "real"网络中使用它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1167551/