北京大学计算机系代亚非19.6一个RMI的分布式应用的实例•用RMI编写一个分布式应用,核心有以下三方面:•定位远程对象–1.一个应用可以利用RMI的名字服务功能注册器远程对象。–2.可以象操作普通对象一样传送并返回一个远程对象的引用(指针)。•与远程对象通信:–底层的通信由RMI实现,对于系统开发人员来说,远程调用和标准的Java方法调用没有什么区别。•为需要传递的对象装载类的字节码–RMI允许调用者向远程对象传递一个对象,因此RMI提供这种装载对象的机制。北京大学计算机系代亚非•本资源由寒秀草与巧克力搜集与网络•请您在传播的时候将下载分数设为0•真正体现资源共享的理念•谢谢•更多0分资料去我的文库2北京大学计算机系代亚非39.6一个RMI的分布式应用的实例WebServerClientServerWebServerregistryURLprotocolRMIRMIURLprotocolURLprotocolRMI北京大学计算机系代亚非49.6一个RMI的分布式应用的实例ComputeenginServerRemoteobjectClienttaskClienttaskClienttask一、问题的提出北京大学计算机系代亚非59.6一个RMI的分布式应用的实例•分布特点:–engin开发,先运行,task后定义.写engin时不对执行什么任务作任何规定.任务可以是任意定制的.•前提条件:–定义任务的类,要规定任务的实现步骤,使得这个任务能够提交给engin去执行.使用server上的CPU资源.•技术支持:–RMI的动态装载功能.北京大学计算机系代亚非69.6一个RMI的分布式应用的实例远程对象clientserverAm1远程方法A.m1()远程对象必须继承远程接口确定那些方法是远程方法,为此定义远程接口远程接口只负责提供方法名,不一共实现细节,因此必须由一个对象来实现接口executeTaskcomputeengineComputeexecuteTask北京大学计算机系代亚非79.6一个RMI的分布式应用的实例•二、设计一个服务器•核心协议:提交任务,执行任务,返回结果clientclient•在java中远程调用是通过定义远程接口来实现的,一个接口只能有一个方法•不同类型的任务,只要他们实现了Task类型,就可以在engin上运行.•实现这个接口的类,可以包含任何任务计算需要的数据以及和任何任务计算需要的方法.北京大学计算机系代亚非89.6一个RMI的分布式应用的实例(1)定义远程接口•第一个接口:computepackagecompute;importjava.rmi.Remote;importjava.rmi.RemoteException;publicinterfaceComputeextendsRemote{ObjectexecuteTask(Taskt)throwsRemoteException;}packagecompute;importjava.io.Serializable;publicinterfaceTaskextendsSerializable{Objectexecute();}第二个接口:定义一个task类型,作为参数传给executeTask方法,规定了engin与它的任务之间的接口,以及如何启动它的任务.它不是一个远程接口executeTaskcomputeengineComputeexecuteTask北京大学计算机系代亚非99.6一个RMI的分布式应用的实例•Computeengin的设计要考虑以下问题:•1.computeengine是一个类ComputeEngine,它实现了Compute接口,只要调用该类的方法executeTask,任务就能提交上来.•2.提交任务的Client端程序并不知道任务是被下载到engin上执行的.因此client在定义任务时并不需要包含如何安装的server端的代码.•3.返回类型是对象,如果结果是基本类型,需要转化成相应的对等类.•4.用规定任务如何执行的代码填写execute方法.北京大学计算机系代亚非109.6一个RMI的分布式应用的实例(2)实现远程接口•一般说来,实现一个远程接口的类至少有以下步骤:•1.声明远程接口•2.为远程对象定义构造函数•3.实现远程方法engin中创建对象的工作可以在实现远程接口类的main函数中实现:•1.创建并安装安全管理器•2.创建一个或更多的远程对象的实例•3.至少注册一个远程对象北京大学计算机系代亚非119.6一个RMI的分布式应用的实例packageengine;importjava.rmi.*;importjava.rmi.server.*;importcompute.*;publicclassComputeEngineextendsUnicastRemoteObjectimplementsCompute{publicComputeEngine()throwsRemoteException{super();}publicObjectexecuteTask(Taskt){returnt.execute();}publicstaticvoidmain(String[]args){if(System.getSecurityManager()==null){System.setSecurityManager(newRMISecurityManager());}Stringname=//host/Compute;try{Computeengine=newComputeEngine();Naming.rebind(name,engine);System.out.println(ComputeEnginebound);}catch(Exceptione){System.err.println(ComputeEngineexception:+e.getMessage());e.printStackTrace();}}北京大学计算机系代亚非129.6一个RMI的分布式应用的实例•在构造函数中,通过super(),aUnicastRemoteObject被启动,即它可以侦听客户端来的请求输入•只有一个远程方法,参数是客户端远程调用这个方法时传来的任务.这个任务被下载到engin,远程方法的内容就是调用客户端任务的方法,并把结果回送给调用者.实际上这个结果是在客户的任务的方法中体现的.executeTaskcomputeengineComputeexecuteTaskcallexecuteTask(task)北京大学计算机系代亚非139.6一个RMI的分布式应用的实例•参数传递规则:•1.远程对象通常通过引用传递.一个远程对象的引用是一个stub,它是客户端的代理.它实现远程对象中的远程接口的内容•2.本地对象通过串行化拷贝到目的.如果不作制定,对象的所有成员都将被拷贝.北京大学计算机系代亚非149.6一个RMI的分布式应用的实例•通过引用传递一个对象,意味着任何由于远程调用引起的变化都能反映在原始的对象中。•当传递一个远程对象时,只有远程接口是可用的,而在实现类中定义的方法或者是非远程接口中的方法,对接收者来说是不可用的•在远程方法调用中,参数,返回值,异常等非对象是值传送.这意味着对象的拷贝被传送到接受方。任何在对象上发生的变化不影响原始的对象•一旦服务器用rmi注册了,main方法就存在了,不需要一个守护线程工作维护服务器的工作状态,只要有一个computerengin的引用在另一个虚拟机,computerengin就不会关闭北京大学计算机系代亚非159.6一个RMI的分布式应用的实例三、实现一个客户程序•目标:创建一个任务,并规定如何执行这个任务。clientPicomputePipackagecompute;publicinterfaceTaskextendsjava.io.Serializable{Objectexecute();}•task不是远程接口,但是需要传递到服务器,因此用串行化ExecuteTask()execute()北京大学计算机系代亚非169.6一个RMI的分布式应用的实例•computePi的作用装载安全管理器生成一个远程对象comp生成任务对象Lookup(ComputeEngin),获得了stubsPitask=newPi()调用ComputeEngin的远程方法获得计算结果Comp.executeTask(task)北京大学计算机系代亚非179.6一个RMI的分布式应用的实例packageclient;importjava.rmi.*;importjava.math.*;importcompute.*;publicclassComputePi{publicstaticvoidmain(Stringargs[]){if(System.getSecurityManager()==null){System.setSecurityManager(newRMISecurityManager());}try{Stringname=//+args[0]+/Compute;Computecomp=(Compute)Naming.lookup(name);Pitask=newPi(Integer.parseInt(args[1]));BigDecimalpi=(BigDecimal)(comp.executeTask(task));System.out.println(pi);}catch(Exceptione){System.err.println(ComputePiexception:+e.getMessage());e.printStackTrace();}}}北京大学计算机系代亚非189.6一个RMI的分布式应用的实例•Pi的作用computepirmiregistryComputeengin实现Task接口实现execute算法北京大学计算机系代亚非199.6一个RMI的分布式应用的实例packageclient;importcompute.*;importjava.math.*;publicclassPiimplementsTask{privatestaticfinalBigDecimalZERO=BigDecimal.valueOf(0);privatestaticfinalBigDecimalONE=BigDecimal.valueOf(1);privatestaticfinalBigDecimalFOUR=BigDecimal.valueOf(4);privatestaticfinalintroundingMode=BigDecimal.ROUND_HALF_EVEN;publicPi(intdigits){this.digits=digits;}北京大学计算机系代亚非209.6一个RMI的分布式应用的实例publicObjectexecute(){returncomputePi(digits);}****************************************************pi/4=4*arctan(1/5)-arctan(1/239)****************************************************publicstaticBigDecimalcomputePi(intdigits){intscale=digits+5;BigDecimalarctan1_5=arctan(5,scale);BigDecimalarctan1_239=arctan(239,scale);BigDecimalpiarctan1_5.multiply(FOUR).subtract(arctan1_239).multiply(FOUR);returnpi.setScale(digits,BigDecimal.ROUND_HALF