我必须如何配置 RMI 环境才能在“真实”环境中使用它? 网络?
因为我不想为基于客户端-服务器的应用程序实现通信协议,所以我在两侧实现了 RMI 客户端和 RMI 服务器,以实现两个组件之间的信息交换。
如果我尝试通过在同一台计算机上启动两个组件来使用我的应用程序,则一切正常。 但是,如果我将组件拆分到两台不同的计算机(Kubuntu 9.04 作为 Windows 7 RC 环境中的虚拟机,禁用防火墙和本机 Ubuntu 9.04 环境),则 RMI 客户端似乎无法执行以下方法:在服务器端定义。 (每个函数调用都会导致RMI异常。)
目前我只将两侧的系统属性“java.rmi.server.hostname”设置为用于数据交换的网络接口,并注册了通信的默认端口与 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”是此处的 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 将程序复制到另一台机器。
Edit2:
嗯,在 /etc/hosts 中设置将机器引用到机器的 IP 地址的条目后,它似乎可以工作,但不太明白为什么会这样......
BR,
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.
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.)
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.
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?
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:
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.
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.
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:
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.
I have no idea why the host is here 127.0.1.1 ...
@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.
Edit2:
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 ...
BR,
Markus
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您需要向机器的
hosts 文件
添加一个条目,其中包含以下
形式的条目: 这将阻止 RMI 将
localhost
主机名作为“回电”地址发送。要测试此方法,请在执行更改之前和之后运行以下代码。
它应该输出更改之前的本地地址和更改之后的非本地地址。
You need to add an entry to the
hosts file
of the machines containing an entry of the forme.g.
This will prevent RMI from sending the
localhost
host name as a 'call me back' address.To test this approach, run the following code before and after performing the change.
It should output a local address before the changes and a non-local address after the changes.
在每台服务器上使用不同版本的 JDK 可能会导致此问题。
使用
java版本
命令以确保您使用相同版本的 jre。
Using different versions of the JDK on each server could cause this problem.
Use the
java -version
command to make sure that you are using the same version of the jre.