本站首页    管理页面    写新日志    退出


«August 2025»
12
3456789
10111213141516
17181920212223
24252627282930
31


公告

戒除浮躁,读好书,交益友


我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:邢红瑞的blog
日志总数:523
评论数量:1142
留言数量:0
访问次数:9690920
建立时间:2004年12月20日




[java语言]RMI 编程 经常遇到的问题
原创空间,  软件技术,  电脑与网络

邢红瑞 发表于 2006/7/18 19:45:12

很久不写RMI程序了,一直使用spring的exporter,人变得懒了。写了一个以后备忘,  创建RMI远程对象后,程序员就可以象调用本地对象那样去调用远程对象,其底层通信机制则完全由RMI实现,无须我们操心了。通常,实现一个RMI系统有4个步骤:1:定义一个remote interface.2:   定义一个remote object implementation.3:   定义客户端程序。4:编译执行远程对象和客户端。 以下为代码示例 服务器端1:Remote接口  (注意:必须extends Remote,方法必须throws RemoteException) 接口import java.rmi.*; public interface RmiHelloRemoteIntfc extends Remote{    public Basic getBasic(Long a) throws RemoteException;}2 remote object implementation.(注意:1:extends UnicastRemoteObject,也可以使用exportObject 2:构造函数内必须调用UnicastRemoteObject的构造函数,也就是执行super())import java.rmi.server.*;import java.rmi.*;import java.util.Random;import java.util.List;import java.util.ArrayList; public class RmiHelloRemoteObj extends UnicastRemoteObject implements RmiHelloRemoteIntfc{        public RmiHelloRemoteObj() throws RemoteException  {    super();     }   public Basic getBasic(Long a) throws RemoteException  {      Random rd=new   Random();        Basic basic=basicList.get(rd.nextInt(84));        System.out.println(basic.getName());        return basic;  } }3 定义远程实现类,在此我把服务器的绑定一起在此类中实现,也可另外再写一个类,实现RMI绑定。(注意:一般都用Naming.rebind(),因为rebind()可以覆盖原有的服务名,省去不必要的麻烦。1099端口为默认,也可以不写)import java.rmi.Naming;import java.rmi.RMISecurityManager;import java.rmi.registry.LocateRegistry; public class RmiHelloServer{   public RmiHelloServer()  {  }  public static void main(String[] args)  {      System.setProperty("java.security.policy","Server.policy");    //创建并安装安全管理器    if(System.getSecurityManager()==null)    {       System.setSecurityManager(new RMISecurityManager());    }     try{         //创建远程对象         RmiHelloRemoteObj obj=new RmiHelloRemoteObj();         //启动注册表         LocateRegistry.createRegistry(2222);         //奖名称绑定到对象         Naming.rebind("rmi://192.168.0.1:2222/helloObj",obj);          System.out.println("RMI服务器正在运行。。。。。。");      }      catch(Exception e)      {         e.printStackTrace();      }   }}jdk 1.5,直接编译就ok。不需要使用rmic生成存根。运行前 unix 执行  rmiregistry &,windwows 在start   rmiregistry前     set   CLASSPATH=.;一下,然后再执行start   rmiregistry否则出现 java.rmi.ServerException:   RemoteException   occurred   in   server   thread;   nested   exce     ption   is:                     java.rmi.UnmarshalException:   error   unmarshalling   arguments;   nested   excep     tion   is:                     java.lang.ClassNotFoundException:   test.PerfectTimeI                     at   sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:385     )                     at   sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:240)                     at   sun.rmi.transport.Transport$1.run(Transport.java:153)  可以不需要 Server.policy但是最好加上grant  { permission java.net.SocketPermission      "*:1000-65535","accept,connect,listen,resolve";};如果客户端过来的端口小于1000,出现java.rmi.UnmarshalException: Error unmarshaling return header; nested exception is:  java.io.EOFException at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source) at sun.rmi.server.UnicastRef.invoke(Unknown Source) at sun.rmi.server.ActivatableRef.invoke(Unknown Source) at ds.rmi.server.ChatServerImpl_Stub.authenticate(Unknown Source) at ds.rmi.client.ClientUI.login(ClientUI.java:142) at ds.rmi.client.ClientUI.start(ClientUI.java:272)        ...Caused by: java.io.EOFException at java.io.DataInputStream.readByte(Unknown Source) ... 8 more如果没有权限,会出现Error:java.security.AccessControlException: access denied(java.net.SockerPermission 127.0.0.1:1099 connect,resolve) 程序里面是没有表明有这样的一个端口被使用的,出现这个异常表明运行服务器权限配置有问题。 要知道对于RMI的C/S之间通信,就像Applet和WebServer之间通信一样,是要受Java的安全沙箱模型约束的。缺省情况下客户端和服务器端的代码没有权限存取硬盘/访问网络等等,这些权限必须在启动客户端和服务器端程序的时候加进去。客户端import java.rmi.Naming;import java.rmi.RMISecurityManager;import java.util.Date; public class RmiHelloClient {     public RmiHelloClient() {    }     public static void main(String[] args) {              System.setProperty("java.security.policy", "Client.policy");        //创建并安装安全管理器        if (System.getSecurityManager() == null) {            System.setSecurityManager(new RMISecurityManager());        }        try {             RmiHelloRemoteIntfc c1 = (RmiHelloRemoteIntfc) Naming.lookup("rmi://192.168.0.1:2222/helloObj");                           Basic basic = c1.getBasic(323L);                                  }        catch (Exception e) {            e.printStackTrace();        }        System.exit(0);     }}客户端策略grant {  permission java.net.SocketPermission      "*:1000-9999","accept,connect,listen,resolve";};


阅读全文(4054) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.078 second(s), page refreshed 144763469 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号