首页 > 代码库 > RMI
RMI
RMI(远程接口调用)
1. RMI的原理:
RMI系统结构,在客户端和服务器端都有几层结构。
方法调用从客户对象经占位程序(Stub)、远程引用层(Remote Reference Layer)和传输层(Transport Layer)向下,传递给主机,然后再次经传 输层,向上穿过远程调用层和骨干网(Skeleton),到达服务器对象。 占位程序扮演着远程服务器对象的代理的角色,使该对象可被客户激活。 远程引用层处理语义、管理单一或多重对象的通信,决定调用是应发往一个服务器还是多个。传输层管理实际的连接,并且追追踪可以接受方法调用的远程对象。服务器端的骨干网完成对服务器对象实际的方法调用,并获取返回值。返回值向下经远程引用层、服务器端的传输层传递回客户端,再向上经传输层和远程调用层返回。最后,占位程序获得返回值。
2. RMI(远程方法调用)的组成
一个正常工作的RMI系统由下面几个部分组成:
?远程服务的接口定义
?远程服务接口的具体实现
?桩(Stub)和框架(Skeleton)文件
?一个运行远程服务的服务器
?一个RMI命名服务,它允许客户端去发现这个远程服务
?类文件的提供者(一个HTTP或者FTP服务器)
?一个需要这个远程服务的客户端程序
技术原理
RMI系统结构,在客户端和服务器端都有几层结构。
--------- ----------
| 客户 | |服务器|
---------- ----------
| |
------------- ----------
| 占位程序| |骨干网|
-------------- -----------
| |
------------------------------------
| 远 程 引 用 层 |
------------------------------------
| |
------------------------------------
| 传 输 层 |
------------------------------------
方法调用从客户对象经占位程序(Stub)、远程引用层(Remote Reference Layer)和传输层(Transport Layer)向下,传递给主机,然后再次经传 输层,向上穿过远程调用层和骨干网(Skeleton),到达服务器对象。 占位程序扮演着远程服务器对象的代理的角色,使该对象可被客户激活。 远程引用层处理语义、管理单一或多重对象的通信,决定调用是应发往一个服务器还是多个。传输层管理实际的连接,并且追追踪可以接受方法调用的远程对象。服务器端的骨干网完成对服务器对象实际的方法调用,并获取返回值。返回值向下经远程引用层、服务器端的传输层传递回客户端,再向上经传输层和远程调用层返回。最后,占位程序获得返回值。
要完成以上步骤需要有以下几个步骤:
1、生成一个远程接口
2、实现远程对象(服务器端程序)
3、生成占位程序和骨干网(服务器端程序)
4、编写服务器程序
5、编写客户程序
6、注册远程对象
7、启动远程对象
一、远程接口:
import java.rmi.Remote; import java.rmi.RemoteException; public interface Ihello extends Remote{ public String sayHello(String name) throws RemoteException ; public String hello() throws RemoteException; }
实现类:
import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import com.wa.spring.rmi.dao.Ihello; public class HelloImpl extends UnicastRemoteObject implements Ihello { public HelloImpl() throws RemoteException { super(); } public String sayHello(String name) throws RemoteException { return "hello, welcome "+name; } public String hello() throws RemoteException { return "good rmi"; } }
方法要抛出RemoteException否则出现以下异常:
二、实现远程对象创建服务端程序:
import java.net.MalformedURLException; import java.rmi.AlreadyBoundException; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import com.wa.spring.rmi.dao.Ihello; import com.wa.spring.rmi.dao.impl.HelloImpl; /** * * @author Administrator * 创建RMI注册表,启动RMI服务,并将远程对象注册到RMI注册表中。 */ public class HelloServer { public static void main(String[] args) { try { //创建一个远程对象 Ihello hello = new HelloImpl(); // //本地主机上的远程对象注册表Registry的实例,并指定端口为8888, //这一步必不可少(Java默认端口是1099),必不可缺的一步,缺少注册表创建,则无法绑定对象到远程注册表上 LocateRegistry.createRegistry(8888); //把远程对象注册到RMI注册服务器上,并命名为Hello //绑定的URL标准格式为:rmi://host:port/name(其中协议名可以省略,下面两种写法都是正确的) Naming.bind("rmi://localhost:8888/Hello",hello); // Naming.bind("//localhost:8888/RHello",rhello); System.out.println("====>>>url绑定成功"); } catch (RemoteException e) { System.out.println("创建远程对象发生异常!"); e.printStackTrace(); } catch (MalformedURLException e) { System.out.println("url异常"); e.printStackTrace(); } catch (AlreadyBoundException e) { System.out.println("重复绑定异常"); e.printStackTrace(); } } }
三、创建客户端程序:
import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException; import com.wa.spring.rmi.dao.Ihello; /** * 在客户端调用远程对象上的远程方法,并返回结果。 * @author Administrator * */ public class HelloClient { public static void main(String[] args) { try { //调用注册的服务 Ihello hello = (Ihello) Naming.lookup("rmi://localhost:8888/Hello"); System.out.println(hello.hello()); System.out.println(hello.sayHello("纳兰容若")); } catch (MalformedURLException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } catch (NotBoundException e) { e.printStackTrace(); } } }
分别运行服务端和客户端可看到输出信息!
参考资料:
http://baike.baidu.com/view/99017.htm?fr=aladdin
http://www.ibm.com/developerworks/cn/java/j-rmiframe/
RMI