- 浏览: 11083 次
- 性别:
- 来自: 北京
最新评论
一.客户与服务器角色
在传统的客户/服务器模式中,客户请求服务器。服务器解析传输的请求,并得到响应,再传给客户端。但是这样必须考虑中间传输格式的解析。如果客户端无须关心请求的传输和解析,只调用本地方法的形式得到结果,但是有时提供服务的对象不再同一个虚拟机内,甚至不是java虚拟机,那怎么办,解决的办法是在客户端提供一个服务器的代理,客户直接调用这个代理,这个代理负责客户与服务器交流。同样,在服务器也安装一个代理负责服务器与客户端通信。并以常规方式调用服务器方法。接下来的问题就是代理之间是怎么通信的呢。
RMI----------------Java远程方法调用技术,支持java的分布式对象之间的调用
CORBA------------通用对象请求架构,支持任何编程语言编写的对象之间的方法调用,CORBA使用Internet inter-ORB协议(IIOP)支持对象间的通信
SOAP--------------简单对象访问协议,它也独立编程语言。基于XML的传输格式。
另外,MicroSoft也使用另一种底层协议COM支持对象间通信。
CORBA和SOAP都是独立于语言的,客户端和服务器完全使用C,C++,Java来编写,只要你提供一种接口描述,以说明你的对象能够处理的方法的签名和数据类型。该接口描述是一种特殊的描述语言,对于CORBA来说接口定义语言是(IDL),对于SOAP则是Web服务描述语言(WSDL)。
CORBA更加高效,而SOAP更适合Web架构的系统。如果通信的对象都是Java实现的,那么最好使用RMI。
二.远程方法调用
客户端对象------------------一般是发起远程调用的对象
服务器对象------------------相应的远程对象
2.1 存根和参数编组
存根-------------当客户端代码调用一个远程方法时,实际上是调用的一个本地方法,我们称此代理对象为存根,存根位于客户端上,而不是服务器上,存根将调用远程方法所需的参数打包成一组字节,这个打包过程是与硬件无关的编码的编码方式进行编码。
参数编组--------对参数编码的过程叫参数编组,它的目的是将参数转换成适合在虚拟机传输的格式。
总之,客户端的存根构造一个信息块,它由以下几部分组成:
- 被使用的远程对象的标示符
- 被调用的方法的描述
- 编组后的参数
然后将这个信息块发送到服务器,服务器接受对象为每个远程方法执行以下动作
- 反编组参数
- 定位要调用的对象
- 调用所需的方法
- 捕获返回值或者调用产生的异常,对它进行编组;
- 对返回值编组,打包送回客户端存根
客户端存根对接受到得返回值编组进行反编组,如果远程方法抛出异常,客户端存根在客户端处理空间中重新抛出异常。
2.2 动态类加载
当一个远程对象,作为远程方法的参数或者返回值,传递给另一个程序时,该程序很显然需要这个对象的Class文件。
三.配置远程方法调用
首先,你必须在客户端和服务器同时运行程序,其次,必要的对象信息被划分为客户端接口和服务器实现。还有专门的查询机制,能够使得客户端准确定位服务器上的对象
3.1 接口与实现
客户端可能需要操纵服务器对象,但是实际上它并不需要真正的服务器对象的引用,因为它只要知道这个对象时干什么的就可以了,我们可以使用接口的方式来描述它能做什么。而这些接口是客户端和服务器共享的,它必须同时存在于客户端和服务器。注意的是远程对象的接口必须继承与Remote。而且必须抛出RemoteException异常。
package rmi; import java.rmi.Remote; import java.rmi.RemoteException; public interface Product extends Remote { String getDescription() throws RemoteException; }
然后呢,在服务器必须实现这个接口
服务器类通常继承RemoteServer。
package rmi; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; public class ProductImpl extends UnicastRemoteObject implements Product { private String desc; public ProductImpl(String desc) throws RemoteException { super(); this.desc = desc; } @Override public String getDescription() throws RemoteException { // TODO Auto-generated method stub return "I am a "+desc+"buy me!"; } }
3.2 存根类生成
从JDK5.0开始,存根类可以自动生成,但是在这之前,存根类必须手动生成:
rmic -v1.2 ProductImpl
它会生成两个文件ProductImpl_Stub.class和ProductImpl_Skel.class
3.3 定位服务器对象
要访问服务器的远程对象,必须获得一个客户端存根,最直接的方法时调用远程方法,获得返回值返回存根,但是这样第一个远程对象怎么获得呢。RMI类库提供了自举注册服务来定位第一个服务器对象。通过给自举注册服务提供一份对象的引用和名字,就可以注册服务器对象,客户端就可以获得对象的存根。这些对象的名称最好唯一。
package rmi; import java.rmi.RemoteException; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; public class ProductServer { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub try { System.out.println("Constructing server implementations..."); ProductImpl p1=new ProductImpl("boy"); ProductImpl p2=new ProductImpl("girl"); System.out.println("Binding server implementations to registry..."); Context namingContext = new InitialContext(); namingContext.bind("rmi:b",p1); namingContext.bind("rmi:g",p2); System.out.println("Waiting for invocation from clients...."); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NamingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
1.启动服务器(windows)
start rmiregistry
start java ProductServer
2.列举远程对象
NamingEnumeration<NameClassPair> e = namingContext.list("rmi:");
package rmi2.ShowBindings; /** @version 1.10 2004-08-14 @author Cay Horstmann */ import java.rmi.*; import java.rmi.server.*; import javax.naming.*; /** This programs shows all RMI bindings. */ public class ShowBindings { public static void main(String[] args) { try { Context namingContext = new InitialContext(); NamingEnumeration<NameClassPair> e = namingContext.list("rmi:"); while (e.hasMore()) System.out.println(e.next().getName()); } catch (Exception e) { e.printStackTrace(); } } }
3.4 编写客户端代码
使用RMI的客户端必须安装一个安全管理器,用以动态加载存根的行为。
System.setSecurityManager(new RMIsetSecurityManager)
package rmi2.Product; /** @version 1.20 2004-08-15 @author Cay Horstmann */ import java.rmi.*; import java.rmi.server.*; import javax.naming.*; /** This program demonstrates how to call a remote method on two objects that are located through the naming service. */ public class ProductClient { public static void main(String[] args) { System.setProperty("java.security.policy", "client.policy"); System.setSecurityManager(new RMISecurityManager()); String url = "rmi://localhost/"; // change to "rmi://yourserver.com/" when server runs on remote machine yourserver.com try { Context namingContext = new InitialContext(); Product c1 = (Product) namingContext.lookup(url + "toaster"); Product c2 = (Product) namingContext.lookup(url + "microwave"); System.out.println(c1.getDescription()); System.out.println(c2.getDescription()); } catch (Exception e) { e.printStackTrace(); } } }
要允许客户端连接RMI注册表以及服务器对象,必须提供一个策略文件。服务器对象使用的是大于1024的端口,RMI默认端口是1099.
client.policy
grant { permission java.net.SocketPermission "*:1024-65535", "connect,accept"; permission java.net.SocketPermission "localhost:80", "connect"; };
总之。
- 编译接口,实现类,服务器类,客户端类等文件
- 启动RMI注册表 start rmiregistry
对于RMI的部署相当的麻烦,一般初学者很容易出错,我也没有深入研究学习,在这里我也不说了。有兴趣的人可以上Google搜索。
四.远程方法的参数传递
4.1 传递非远程对象
当一个不是远程对象的对象,需要从一个java虚拟机传送另外一个java虚拟机时,第一个java虚拟机会制作一个对象COPY,然后通过网络传送到另外一个虚拟机,当你将对象传递到本地方法的是,传递的只是引用。
所以远程对象通过存根传递的,非远程对象通过复制传递。
无论何时,当调用远程方法的时候,存根将所有参数值的副本打包,发给服务器,其中用到了对象序列化机制编组参数。
发表评论
-
QQ2010山寨版--可聊天
2011-02-28 17:08 670QQ山寨比较多,前段时间密码被盗了,用了几年的QQ,密码被盗, ... -
jaf 简介
2010-11-10 15:30 0JavaBeans激活框架(JavaBeans Activ ... -
request的小问题
2010-04-15 15:46 861有段时间弄一个聊天程序: 想得到IP使用request.ge ... -
Java安全机制
2010-04-14 17:56 1280Java安全 java通过以下技术来实现安全机制 语言设 ... -
Swing基础知识学习
2010-04-14 16:09 2500高级Swing学习 一.列表 1.1 JList构件 J ... -
线程知识复习
2010-04-13 11:11 1149一.线程的实现方式 1.继承Thread 2.实现Runn ...
相关推荐
JAVA远程调用RMI与应用
java实现远程调用的完整实例,可在linux环境下启动远程服务,window下执行操作。代码有详细说明。
远程调用代码RMI技术,可是实现远程方法调用的代码
RMI远程方法调用RMI远程方法调用RMI远程方法调用RMI远程方法调用RMI远程方法调用
java rmi 实现远程调用服务的简单的例子。
本文档主要讲述的是Java 远程方法调用RMI参数详解;根据RMI参数意义,可以归结为以下几点,我们可以根据这几点通过优化GC, 网络等待,流传输协议(http/rmi special socket)等方面来优化RMI。
三种方式实现java远程调用(rmi) 方式一:原始方式 方式二:spring 方式三:jndi 解压,放到myeclipse上可用
1. 远程调用RMI(Remote Method Invocation): 通过使用 RmiProxyFactoryBean 和 RmiServiceExporter,并且,Spring支持两个传统的RMI(使用 java.rmi.Remote接口和java.rmi.RemoteException)和通过RMI调用器实现的...
用java的rmi实现的 远程调用。希望对阁下有用
这个是基于C#的 RMI远程方法调用 这个是基于C#的 RMI远程方法调用这个是基于C#的 RMI远程方法调用
JAVA RMI远程调用方法代码 RMI 远程 java
RMI简单远程调用,实现数字相加!代码简单易懂
RMI采用JRMP(Java Remote Method Protocol)通讯协议,是构建在TCP/IP协议上的一种远程调用方法。它允许运行在一个Java虚拟机上的对象调用运行在另一个Java虚拟机上的对象方法,从而使编程人员可以方便地在网络环境...
java jdk1.8; eclipse 开发环境;实现A机器的程序,可以管理(增加、删除、改等)B机器上的某个文件夹或者目录;掌握远程过程调用原理,基于...客户端利用RMI实现远程调用服务。同时,在在两台机器之间验证结果正确。
最近在学习代理模式,用到了java rmi远程调用,包含服务端和客户端,之前一直没有接触过,学习了java rmi远程调用,一方面可以了解代理模式,一方面熟悉java低层的远程
安装$ mvn install$ java -Djava.security.policy=RMI-Server/server.policy -jar RMI-Server/target/RMI-Server-1.0.jar$ java -Djava.security.policy=RMI-Client/client.policy -jar RMI-Client/target/RMI-...
RMI远程调用,之前做的Demo希望对大家有所帮助!
rmi 远程方法调用 客户端
有很多关于rmi的调用说明,在最后的运行时总是不太详细,通过多方查阅,写了一段代码,供大家参考,希望对大家有帮助。
spring RMI 远程接口调用 包含服务端客户端程序,可完整运行