最简单的rmi例子

来源:互联网 发布:linux查找字符串快捷键 编辑:程序博客网 时间:2024/04/30 00:07

一个正常工作的RMI系统由下面几个部分组成: 
1、远程服务的接口定义 
2、远程服务接口的具体实现 
3、桩(Stub)和框架(Skeleton)文件 
4、一个运行远程服务的服务器 
5、一个RMI命名服务,它允许客户端去发现这个远程服务 
6、类文件的提供者(一个HTTP或者FTP服务器) 
7、一个需要这个远程服务的客户端程序 
二、RMI(远程方法调用)的工作原理 
RMI系统结构,在客户端和服务器端都有几层结构。 
--------- ---------- 
| 客户 | | 服务器| 
---------- ---------- 
| | 
------------- ---------- 
| 占位程序 | | 骨干网 | 
-------------- ----------- 
| | 
------------------------------------ 
| 远 程 引 用 层 | 
------------------------------------ 
| | 
------------------------------------ 
| 传 输 层 | 
------------------------------------ 

方法调用从客户对象经占位程序(Stub)、远程引用层(Remote Reference Layer)和传输层(Transport Layer)向下,传递给主机,然后再次经传 输层,向上穿过远程调用层和骨干网(Skeleton),到达服务器对象。 占位程序扮演着远程服务器对象的代理的角色,使该对象可被客户激活。 远程引用层处理语义、管理单一或多重对象的通信,决定调用是应发往一个服务器还是多个。传输层管理实际的连接,并且追追踪可以接受方法调用的远程对象。服务器端的骨干网完成对服务器对象实际的方法调用,并获取返回值。返回值向下经远程引用层、服务器端的传输层传递回客户端,再向上经传输层和远程调用层返回。最后,占位程序获得返回值。 

步骤1:定义rmi服务接口,需要从Remote接口扩展,注意其中的方法必须抛出RemoteException异常,否则无法绑定:

package rmi;

 

import java.rmi.Remote;

import java.rmi.RemoteException;

 

 

public interface NameService extends Remote{

/**

* 必须抛出RemoteException异常,否则无法绑定

* @return

* @throws RemoteException

*/

    String getName()throws RemoteException;

}

步骤2:实现rmi接口,注意实现类从UnicastRemoteObject继承, 所有可以被远程调用的对象都必须扩展该类,让客户机与服务器对象实例建立一对一的连接:

package rmi;

 

import java.io.Serializable;

import java.net.MalformedURLException;

import java.rmi.AlreadyBoundException;

import java.rmi.Naming;

import java.rmi.NotBoundException;

import java.rmi.RemoteException;

import java.rmi.registry.LocateRegistry;

import java.rmi.registry.Registry;

import java.rmi.server.UnicastRemoteObject;

/**

 * 一般从UnicastRemoteObject继承, 所有可以被远程调用的对象都必须扩展该类,让客户机与服务器对象实例建立一对一的连接

 * @author yandong_yu

 *

 */

public class NameServiceimpl  implements NameService{

/**

* 必须定义构造方法,因为要抛出RemoteException异常 

* @throws RemoteException

*/

protected NameServiceimpl() throws RemoteException {

super();

}

/**

*/

private static final long serialVersionUID = 6049452763111963360L;

 

@Override

public String getName()throws RemoteException {

return "yuyd";

}

}

步骤3:注册类:

public static void main(String[] args) throws RemoteException, MalformedURLException, AlreadyBoundException, NotBoundException{

        String ip = "localhost";  

int port = 8889;  

/**

* 创建该端口对应的注册对象,该注册对象内部有一个hashTable,维护了ServiceName到服务对象的对应关系

*/

Registry reg=LocateRegistry.createRegistry(port);

NameServiceimpl service = new NameServiceimpl();

/**

* 绑定一个ip,端口和服务名,该方法会在Registry上面创建一个nameservice为key值的服务对象

*/

Naming.rebind("//" + ip + ":" + port + "/nameservice", service);

System.out.println("register rmi successful");

}

步骤4:客户端调用:

public static void main(String[] args) throws RemoteException, MalformedURLException, AlreadyBoundException, NotBoundException{

        String ip = "localhost";  

int port = 8889;  

/**

* clientService是一种远端实现

*/

NameService clientService = (NameService)Naming.lookup("//" + ip + ":" + port + "/nameservice");

if(clientService!=null){

System.out.println("lookup rmi successful");

System.out.println(clientService.getName());

}

 

}