RMI远程方法调用概述

最近在学RMI远程调用,今天终于把《Java高级编程:JDK5》中的范例代码调试成功了,现在把我在调试中遇到的问题总结一下,有兴趣的朋友可以看一下,本程序jdk版本为1.6,平台为WinXP。

 

此范例主要完成一个聊天室的功能,共有四个类、一个嵌入Applet的htm网页和一个安全策略文件,分别是:

 

RMIChat接口

RMIChatImpl类

ChatUser类

ChatApplet类

test.htm

rmi.policy

 

为了更详细的叙述,下面结合代码进行讲述,具体的步骤为:

 

1、定义RMIChat接口

 

此接口实现必须扩展java.rmi.Remote接口,并且该接口中定义的方法必须抛出RemoteException,代码如下:

 

  

 

2,实现RMIChatImpl类

 

该类是实现RMIChat接口的类。它定义了在RMIChat接口中存在的每一个方法,它的主要目的是作为一个服务来连接RMIClient。此类需要注册到RMI注册表。代码如下:


  

 

这个类的main方法非常重要,他完成RMIChatImpl对象到RMI注册表的的注册,下面对其进行分析:

 

1、首先它设置一个用于服务器的安全管理器。可以裁剪安全管理器以适应体系结构的需要,这个简单的示例只是使用了默认的系统安全管理。

2、然后它构造一个RMIChatImpl对象,该对象将被注册到RMI注册表。

3、最后,它使用Naming.bind方法将RMIChatImpl对象绑定到注册表中的“RMIChatServer”名称上。客户端可以搜索“RMIChatSe rver”来获得一个远程RMIChatImpl对象。

 

注意:RMI注册表必须在上述步骤之前启动,以确保对RMI注册表的正确注册操作。下面会有体现。

 

 

3、定义ChatUser类

 

ChatUser类用来存储有关RMIChatImpl服务器用户的特定信息,该类是客户端和服务器端都要用到的。代码如下:

 

  

 

4、定义ChatApplet类

ChatApplet类是用于客户端的类,该范例中用一个Applet小程序来实现客户端的功能。ChatApplet类并不需要扩展或者实现任何特定的RMI接口或者类,我们知道RMI远程方法调用对于用户来说和调用本地类是没有任何区别的,所以客户端是一个瘦客户端。该类的代码如下:

 

 

 

5、下面定义test.htm网页的内容

<html>
 <body>
  <applet CODE=ChatApplet.class width="300" height="200" >
  </applet>
 </body>
</html>

 

6、编写策略文件,命名为rmi.policy,文件内容很简单,如下:

 

grant {
  permission java.net.SocketPermission "*:1024-65535", "accept,connect,listen,resolve"; //(1.1)
  permission java.net.SocketPermission "*:80", "accept,connect,listen,resolve";  //(1.2)

  //上面两行代码也可以不要,我自己试了不要也可以,但是网上有篇文章说必须在AllPermission的基础上加这两行,不知道为什么读者可以自己试一下
  permission java.security.AllPermission;


};


7、编译文件并测试

 

7.1将上面的五个文件放到D:/chat/文件夹下面,分别编译RMIChat.java,RMIChatImpl.java,ChatUser.java和ChatApplet.java。

7.2运行java的rmic工具,在命令提示符窗口输入“rmic RMIChatImpl”单击回车,生成对应RMIChatImpl的存根文件RMIChatImpl_Stub.class。

7.3启动RMI注册表,这一步是必须的,命令格式为start rmiregistry。

7.4运行服务器端程序RMIChatImpl,命令如下:

 

D:/chat> java -Djava.security.policy=file:./rmi.policy -Djava.rmi.server.codebase=file:./RMIChatImpl RMIChatImpl

 

7.5运行test.htm文件,测试该聊天室程序。开两个命令提示符窗口,分别输入下面的命令,然后进行聊天室验证。

 

D:/chat>appletviewer test.htm

 

如果你的Applet小程序可以成功通信,恭喜,你成功了,你已经成功的创建了一个RMI系统,并且使它正确工作了。即使你运行在同一个计算机上,RMI还是使用了你的网络堆栈和TCP/IP去进行通讯,并且是运行在三个不同的Java虚拟机上。这已经是一个完整的RMI系统。

 

8、问题总结

 

8.1问题一

 

刚开始反复编译,出现如下错误

D:/chat> java -Djava.security.policy=file:./rmi.policy -Djava.rmi.server.codebase=file:./RMIChatImpl RMIChatImpl
RMIserver erroraccess denied (java.net.SocketPermission 127.0.0.1:1099 conne
esolve)
java.security.AccessControlException: access denied (java.net.SocketPermissi
27.0.0.1:1099 connect,resolve)

 

原因为我的rmi.policy策略文件配置有误,程序运行受到安全策略的限制。

 

8.2问题二

所有的类都编译成功之后,按照上面的步骤进行测试,但是每当运行RMIChatImpl的时候就报出下面的错误

 

上面代码可能有点儿乱,其中心意思就是RMIChatImpl_Stub.class这个文件找不到,这究竟是什么原因呢,我明明已经成功编译出了这个文件啊?通过认真思索终于找到了原因所在,如下:

 

刚开始我运行RMI注册表时所在目录为:C:/Documents and Settings/Administrator>rmiregistry,在此目录下,注册表的确可以顺利启动,但是它对chat目录下的程序运行根本不起作用。然后进行改正,在chat目录下运行RMI注册表,然后再运行RMIChatImpl,可以成功运行。

 

8.3问题三

 

本示例中所有的类文件都放到了一个文件夹下(chat文件夹),但实际情况是服务器端和客户端肯定不是在一个目录下的,下面将客户端和服务器端文件进行分离,进行程序测试。

 

在f:/根目录下创建两个文件夹chatS和chatC,分别存放服务器端和客户端的文件,chatS文件夹下的文件为RMIChatImpl.class,RMIChat.class,ChatUser.class,rmi.policy和RMIChatImpl_Stub.class文件,chatC文件夹下的文件为ChatApplet.class , ChatApplet$1.calss , ChatApplet$2.class , ChatUser.class,RMIChat.class和test.htm文件。

 

依照前面的测试步骤,在chatS文件夹下RMI注册表和RMIChatImpl都可顺利执行,但是在chatC文件夹下运行ChatApplet时提示我RMIChatImpl_Stub.class文件找不到,看来此文件是客户端必须的(不论Applet还是application),然后将该stub文件复制到chatC文件夹下执行,可以顺利执行。

 

8.4问题四

 

我在另一个rmi测试程序的练习中,对编译后的文件进行rmic处理时,生成的文件有两个,一个是_Stub结尾的,另一个是_Skel结尾的,二本程序之生成了一个Stub文件。我从网上找原因,有一个答案是不同版本jdk的原因,但是我是在相同的机器上测试的,这个问题还未解决,希望高手赐教。

 

8.5问题五

 

客户端程序需不需要安全策略文件呢?我自己编写了一个rmi程序,发现直接输入“java client”客户端即可顺利执行,但是该页面的http://blog.csdn.net/goleagle/archive/2009/04/25/4107853.aspx一篇文章说到,客户端需要安全策略文件才可以执行,否则会抛出异常,看来应该和具体的配置有关系。

 

8.6问题六

程序的发布问题,该程序客户端是Applet程序,怎样保证从浏览器端正确运行该测试程序呢?在chat目录下直接运行test.htm肯定不行,你可以试试,此时浏览器可以显示界面,但无法和服务端连接。程序该如何发布呢?我进行了如下操作:

 

首先,把Chat文件夹复制到Tomcat服务器的Root目录下。

然后,将Chat 文件夹下的 ChatApplet$1.class , ChatApplet$2.class , ChatApplet.class , RMIChat.class 和RMIChatImpl_Stub.class文件打包生成test.jar文件。

其次,修改test.htm文档中的内容,如下:

<html>
 <body>
  <applet archive=test.jar CODE=ChatApplet.class width="300" height="200" >
  </applet>
 </body>
</html>

最后,运行RMI注册表和RMIChatImpl,成功运行后,在IE浏览器中输入localhost:8080/chat/test.htm,单击回车,发现返回正常的Applet页面,进行连接测试,发现仍然无法成功链接到服务器端程序,这究竟是什么原因呢?

 

从网上找原因,有n种答案,主要就是这两种:

 

1.安全性限制,需要修改客户端的安全策略文件,或者运用数字签名

2.IE不支持java2

 

本人进行反复实验就是无法找到本质原因,希望有谁看到这篇文章能够成功解决这一问题。

 


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/goleagle/archive/2009/04/25/4107853.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值