1

我成功创建了 RMI 服务和客户端。我可以调用方法等等。但现在我想尝试以下方法:我希望在服务上托管一个标准的 Java 对象,如 LinkedList。此外,我想“假装”我已经拥有使用 LinkedList 的现有代码。我想要的是获得一个实际上由服务管理的 LinkedList,但我可以像普通的 LinkedList 一样在本地访问它。最重要的是,我想做一些最小的日志记录,比如如果 .add() 被调用,它会在服务器上写入:“添加调用”。

这不是为了生产,只是为了帮助我理解它是如何工作的!

到目前为止,我已经尝试了很多东西。最有希望的是我创建了一个扩展 LinkedList 并实现 Remote 的类。此类尝试在构造函数中向 Registry 注册自己,如下所示:

try {

UnicastRemoteObject.exportObject((Remote)this); Naming.rebind("theList", (Remote)this); } catch (Exception e) { System.out.println("fail"); System.out.println(e.getMessage()); }

我必须这样做,因为我需要扩展 LinkedList,因此我无法扩展 UnicastRemoteObject。

当我尝试在服务器端运行它时得到的输出:

失败
连接拒绝主机:192.168.178.27;嵌套异常是:
 java.net.ConnectException:连接被拒绝

在客户端:

java.lang.ClassCastException:MyList_Stub 无法转换为 java.util.LinkedList
 在 $Proxy0.createList(未知来源)
 在 RemoteProgram.main(RemoteProgram.java:27)

提前致谢!

4

3 回答 3

2

您正在尝试做的事情效率很低,而且不是一个好主意。基本上,您可以在可以序列化的方法调用中发送任何内容。如果您想要良好的性能,我建议您只有一个远程对象来代表您的服务并充当您需要的所有服务的外观(每个远程对象都会产生单独的文件描述符,因此拥有大量远程对象通常是不是一个好主意)。此外,如果您经常添加和删除对象,那么每次添加或删除元素时都发送消息是不明智的。我建议使用以下两种非常简单的方法来创建一个远程对象:

LinkedList retrieveLinkedListByName(String);
boolean commitNewVersionOfLinkedListByName(String,LinkedList);

在应用程序启动时,您可以下载链表,然后在定期和应用程序退出时,您可以发送回链表。每次在链表中添加或删除元素时,这应该比使用网络更有效。只要你的 LinkedList 的元素是可序列化的,你就不需要做任何魔法(比如扩展远程)来发送它。

于 2010-07-11T11:32:12.253 回答
2
java.lang.ClassCastException: MyList_Stub cannot be cast to java.util.LinkedList
at $Proxy0.createList(Unknown Source)
at RemoteProgram.main(RemoteProgram.java:27)

LinkedList 是一个具体的类,RMI 与接口一起使用,因此您应该在客户端转换为 List 接口。

于 2010-07-11T11:35:38.207 回答
0

同意其他海报,这是一个非常低效的设计。

至于您的例外情况,我不知道您如何在服务器中获得“连接被拒绝”并且仍然能够运行客户端。您需要发布堆栈跟踪。

于 2010-07-12T06:43:31.440 回答