java rmi (2)Java RMI 简单示例

以下用一个最简单的Hello的示例来介绍RMI的应用。

1定义一个远程接口

IHello.java代码如下

import  java.rmi.Remote;

public   interface  IHello  extends  Remote {

public  String sayHello(String name)  throws  java.rmi.RemoteException;

}


2实现远程的接口(服务端就在此远程接口的实现类中)

HelloImpl.java代码如下

import  java.rmi.RemoteException;
import  java.rmi.server.UnicastRemoteObject;
public   class  HelloImpl  extends  UnicastRemoteObject  implements  IHello {
    
//  这个实现必须有一个显式的构造函数,并且要抛出一个RemoteException异常  
     protected  HelloImpl()  throws  RemoteException {
        
super ();
    }
    
/**
     * 说明清楚此属性的业务含义
     
*/
    
private   static   final   long  serialVersionUID  =   4077329331699640331L ;
    
public  String sayHello(String name)  throws  RemoteException {
        
return   " Hello  "   +  name  +   "  ^_^  " ;
    }
    
public   static   void  main(String[] args) {
        
try  {
            IHello hello 
=   new  HelloImpl();
            java.rmi.Naming.rebind(
" rmi://localhost:1099/hello " , hello);
            System.out.print(
" Ready " );
        } 
catch  (Exception e) {
            e.printStackTrace();
        }
    }
}


3:新建RMI客户端调用程序

Hello_RMI_Client.java代码如下

import  java.rmi.Naming;
public   class  Hello_RMI_Client {
    
public   static   void  main(String[] args) {
        
try  {
            IHello hello 
=  (IHello) Naming.lookup( " rmi://localhost:1099/hello " );
                System.out.println(hello.sayHello(
" zhangxianxin " ));
        } 
catch  (Exception e) {
            e.printStackTrace();
        }
    }
}


4:编译并运行

4.1 javac命令编译IHello.javaHelloImpl.javaHello_RMI_Client.java

>javac *.java

4.2 rmic命令生成桩和框架文件

 >rmic HelloImpl

成功执行完上面的命令可以发现生成一个HelloImpl_stub.class文件,如果JDK是使用Java2SDK,那么还可以发现多出一个HelloImpl_Skel.class文件。如果服务端程序与客户端程序在同一台机器上并在同一目录中,则可以省略掉接口实现类生成的桩和框架文件,但这就失去了使用RMI的意义,而如果要在不同的JVM上运行时,客户端程序就必须得依靠服务端运程方法实现的桩和框架文件以及接口类。

4.3 运行注册程序RMIRegistry,必须在包含刚写的类的目录下运行这个注册程序。

>rmiregistry

注册程序开始运行了,不要管他,现在切换到另外一个控制台运行服务器 

4.4 运行服务器HelloImpl

>java HelloImpl

当启动成功出现Ready...... 这个服务器就开始工作了,把接口的实现加载到内存等待客户端的联接。现在切换到第三个控制台,启动我们的客户端。

4.5 启动客户端:为了在其他的机器运行客户端程序你需要一个远程接口(IHello.class) 和一个stub(HelloImpl_Stub.class)。 使用如下命令运行客户端

>java Hello_RMI_Client

当运行成功会在控制台打印:Hello zhangxianxin ^_^

备注:如果不想在控制台上开启RMI注册程序RMIRegistry的话,可在RMI服务类程序中添加LocateRegistry.createRegistry(1099); 如下所示:

修改后的HelloImpl.java代码如下

import  java.rmi.RemoteException;
import  java.rmi.registry.LocateRegistry;
import  java.rmi.server.UnicastRemoteObject;
public   class  HelloImpl  extends  UnicastRemoteObject  implements  IHello {
    
//  这个实现必须有一个显式的构造函数,并且要抛出一个RemoteException异常  
     protected  HelloImpl()  throws  RemoteException {
        
super ();
    }
    
    
private   static   final   long  serialVersionUID  =   4077329331699640331L ;
    
public  String sayHello(String name)  throws  RemoteException {
        
return   " Hello  "   +  name  +   "  ^_^  " ;
    }
    
public   static   void  main(String[] args) {
        
try  {
            IHello hello 
=   new  HelloImpl();
            LocateRegistry.createRegistry(
1099 );  // 加上此程序,就可以不要在控制台上开启RMI的注册程序,1099是RMI服务监视的默认端口
            java.rmi.Naming.rebind( " rmi://localhost:1099/hello " , hello);
            System.out.print(
" Ready " );
        } 
catch  (Exception e) {
            e.printStackTrace();
        }
    }
    }


Java RMI 简单示例二

以下用一个文件交换程序来介绍RMI的应用。这个应用允许客户端从服务端交换(或下载)所有类型的文件。第一步是定义一个远程的接口,这个接口指定的签名方法将被服务端提供和被客户端调用。

1.定义一个远程接口 

IFileUtil.java代码如下

import  java.rmi.Remote;

import  java.rmi.RemoteException;

public   interface  IFileUtil  extends  Remote {

public   byte [] downloadFile(String fileName)  throws  RemoteException;

}

接口IFileDownload提供了一个downloadFile方法,然后返回一个相应的文件数据。

2.实现远程的接口 
  FileImpl继承于UnicastRemoteObject类。这显示出FileImpl类是用来创建一个单独的、不能复制的、远程的对象,这个对象使用RMI默认的基于TCP的通信方式。

FileUtilImpl.java代码如下:


import  java.io.BufferedInputStream;

import  java.io.File;

import  java.io.FileInputStream;

import  java.rmi.RemoteException;

import  java.rmi.server.UnicastRemoteObject;

public   class  FileUtilImpl  extends  UnicastRemoteObject  implements  IFileUtil {

protected  FileUtilImpl()  throws  RemoteException {

super ();

}

private   static   final   long  serialVersionUID  =   7594622080290821912L ;

public   byte [] downloadFile(String fileName)  throws  RemoteException{

File file 
=   new  File(fileName);

byte  buffer[]  =   new   byte [( int ) file.length()];

int  size  =  buffer.length;

System.out.println(
" download file size =  " + size  + " b " );

if (size > 1024 * 1024 * 10 ){ // 限制文件大小不能超过10M,文件太大可能导制内存溢出!

throw   new  RemoteException( " Error:<The File is too big!> " );

}

try  {

BufferedInputStream input 
=   new  BufferedInputStream(

new  FileInputStream(fileName));

input.read(buffer, 
0 , buffer.length);

input.close();

System.out.println(
" Info:<downloadFile() hed execute successful!> " );

return  buffer;

catch  (Exception e) {

System.out.println(
" FileUtilImpl:  "   +  e.getMessage());

e.printStackTrace();

return   null ;

}

}

}

3.编写服务端 

1)创建并安装一个RMISecurityManager实例。

2)创建一个远程对象的实例。

3)使用RMI注册工具来注册这个对象。

FileUtilServer.java 代码如下:

import  java.rmi.Naming;

import  java.rmi.RMISecurityManager;

public   class  FileUtilServer {

public   static   void  main(String argv[]) {

try  {

IFileUtil file 
=   new  FileUtilImpl();

// LocateRegistry.createRegistry(1099);  // 加上此程序,就可以不要在控制台上开启RMI的注册程序,1099是RMI服务监视的默认端口

Naming.rebind(
" rmi://127.0.0.1/FileUtilServer " , file);

System.out.print(
" Ready " );

catch  (Exception e) {

System.out.println(
" FileUtilServer:  "   +  e.getMessage());

e.printStackTrace();

}
}
}

声明Naming.rebind("rmi://127.0.0.1/FileUtilServer", file中假定了RMI注册工具(RMI registry )使用并启动了1099端口。如果在其他端口运行了RMI注册工具,则必须在这个声明中定义。例如,如果RMI注册工具在4500端口运行,则声明应为:  Naming.rebind("rmi://127.0.0.1:4500/FileUtilServer", file

另外我们已经同时假定了我们的服务端和RMI注册工具是运行在同一台机器上的。否则需要修改rebind方法中的地址。


4.编写客户端 

客户端可以远程调用远程接口(FileInterface)中的任何一个方法。无论如何实现,客户端必须先从RMI注册工具中获取一个远程对象的引用。当引用获得后,方法downloadFile被调用。在执行过程中,客户端从命令行中获得两个参数,第一个是要下载的文件名,第二个是要下载的机器的地址,在对应地址的机器上运行服务端。

FileUtilClient.java 代码如下:

import  java.io.BufferedOutputStream;

import  java.io.File;

import  java.io.FileOutputStream;

import  java.rmi.Naming;

public   class  FileUtilClient {

public   static   void  main(String args[]) {

if  (args.length  !=   3 ) {

System.out.println(
" 第一个参数:RMI服务的IP地址 " );

System.out.println(
" 第二个参数:要下载的文件名 " );

System.out.println(
" 第三个参数:要文件保存位置 " );

System.exit(
0 );

}

try  {

String name 
=   " rmi:// "   +  args[ 0 +   " /FileUtilServer " ;

IFileUtil fileUtil 
=  (IFileUtil) Naming.lookup(name);

byte [] filedata  =  fileUtil.downloadFile(args[ 1 ]);

if (filedata == null ){

System.out.println(
" Error:<filedata is null!> " );

System.exit(
0 );

}

File file 
=   new  File(args[ 2 ]);

System.out.println(
" file.getAbsolutePath() =  " + file.getAbsolutePath());

BufferedOutputStream output 
=   new  BufferedOutputStream(

new  FileOutputStream(file.getAbsolutePath()));

output.write(filedata, 
0 , filedata.length);

output.flush();

output.close();

System.out.println(
" ~~~~~End~~~~~ " );

catch  (Exception e) {

System.err.println(
" FileUtilServer exception:  "   +  e.getMessage());

e.printStackTrace();

}

}

}


5.运行程序
为了运行程序,我们必须使用rmic来编译生成stubsskeletons:

>rmic FileUtilImpl

这将会生成FileUtilImpl_Stub.classFileUtilImpl_Skel.class两个文件。stub是客户端的代理,而skeleton是服务端的框架。服务端和客户端采用javac来编译(如果服务端和客户端在两个不同的机器,则必须复制一个IFileUtil接口)。

使用rmiregistry或者start rmiregistry 命令来运行RMI注册工具到window系统默认的端口上:
> rmiregistry portNumber
此处的portNumber为端口,RMI注册工具运行之后,需要运行服务FileUtilServer,因为RMI的安全机制将在服务端发生作用,所以必须增加一条安全策略: grant{permission java.security.AllPermission "", "";};

为了运行服务端,需要有除客户类(FileUtilClient.class)之外所有的类文件。确认安全策略在policy.txt文件之后,使用如下命令来运行服务器。
> java -Djava.security.policy=policy.txt FileUtilServer

为了在其他的机器运行客户端程序,需要一个远程接口(IFileUtil.class)和一个stub(FileUtilImpl_Stub.class)。 使用如下命令运行客户端:
> java FileUtilClient fileName machineName savePath
  这里fileName是要下载的文件名,machineName 是要下载的文件所在的机器(也是服务端所在的机器),savePath 是要将下载过来的文件保存的路径(带文件名)。如果全部通过的话,当客户端运行后,则这个文件将被下载到本地。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值