当前位置:  技术问答>java相关

有谁能详细解释一下RMI,可不可以这么认为,RMI就是包装简化了的socket?多谢了

    来源: 互联网  发布时间:2015-11-10

    本文导语:  可不可以这么认为,RMI就是包装简化了的socket?RMI注册表注册实际做了那些事情?简简单单的一句start rmiregistry背后究竟做了什么? | Java RMI (Remote Method Invocation 远程方法调用)是用Java...

可不可以这么认为,RMI就是包装简化了的socket?RMI注册表注册实际做了那些事情?简简单单的一句start rmiregistry背后究竟做了什么?

|
Java RMI (Remote Method Invocation 远程方法调用)是用Java在JDK1.1中实现的,它大大增强了Java开发分布式应用的能力。Java作为一种风靡一时的网络开发语言,其巨大的威力就体现在它强大的开发分布式网络应用的能力上,而RMI就是开发百分之百纯Java的网络分布式应用系统的核心解决方案之一。其实它可以被看作是RPC的Java版本。但是传统RPC并不能很好地应用于分布式对象系统。而Java RMI 则支持存储于不同地址空间的程序级对象之间彼此进行通信,实现远程对象之间的无缝远程调用。RMI目前使用Java远程消息交换协议JRMP(Java Remote Messaging Protocol)进行通信。JRMP是专为Java的远程对象制定的协议。因此,Java RMI具有Java的"Write Once,Run Anywhere"的优点,是分布式应用系统的百分之百纯Java解决方案。用Java RMI开发的应用系统可以部署在任何支持JRE(Java Run Environment Java,运行环境)的平台上。但由于JRMP是专为Java对象制定的,因此,RMI对于用非Java语言开发的应用系统的支持不足。不能与用非Java语言书写的对象进行通信。本文拟从程序的角度举例介绍怎样利用RMI实现Java分布式应用。 
一、RMI系统运行机理

RMI应用程序通常包括两个独立的程序:服务器程序和客户机程序。典型的服务器应用程序将创建多个远程对象,使这些远程对象能够被引用,然后等待客户机调用这些远程对象的方法。而典型的客户机程序则从服务器中得到一个或多个远程对象的引用,然后调用远程对象的方法。RMI为服务器和客户机进行通信和信息传递提供了一种机制。

在与远程对象的通信过程中,RMI使用标准机制:stub和skeleton。远程对象的stub担当远程对象的客户本地代表或代理人角色。调用程序将调用本地stub的方法,而本地stub将负责执行对远程对象的方法调用。在RMI中,远程对象的stub与该远程对象所实现的远程接口集相同。调用stub的方法时将执行下列操作:(1) 初始化与包含远程对象的远程虚拟机的连接;(2) 对远程虚拟机的参数进行编组(写入并传输);(3) 等待方法调用结果;(4) 解编(读取)返回值或返回的异常;(5) 将值返回给调用程序。为了向调用程序展示比较简单的调用机制,stub将参数的序列化和网络级通信等细节隐藏了起来。在远程虚拟机中,每个远程对象都可以有相应的skeleton(在JDK1.2环境中无需使用skeleton)。Skeleton负责将调用分配给实际的远程对象实现。它在接收方法调用时执行下列操作:(1) 解编(读取)远程方法的参数;(2) 调用实际远程对象实现上的方法;(3) 将结果(返回值或异常)编组(写入并传输)给调用程序。stub和skeleton由rmic编译器生成。

利用RMI编写分布式对象应用程序需要完成以下工作:(1) 定位远程对象。应用程序可使用两种机制中的一种得到对远程对象的引用。它既可用RMI的简单命名工具rmiregistry来注册它的远程对象,也可以将远程对象引用作为常规操作的一部分来进行传递和返回。(2)与远程对象通信。远程对象间通信的细节由RMI处理,对于程序员来说,远程通信看起来就像标准的Java方法调用。(3)给作为参数或返回值传递的对象加载类字节码。因为RMI允许调用程序将纯Java对象传给远程对象,所以,RMI将提供必要的机制,既可以加载对象的代码又可以传输对象的数据。在RMI分布式应用程序运行时,服务器调用注册服务程序以使名字与远程对象相关联。客户机在服务器上的注册服务程序中用远程对象的名字查找该远程对象,然后调用它的方法。

二、对象序列化

在RMI分布式应用系统中,服务器与客户机之间传递的Java对象必须是可序列化的对象。不可序列化的对象不能在对象流中进行传递。对象序列化扩展了核心Java输入/输出类,同时也支持对象。对象序列化支持把对象编码以及将通过它们可访问到的对象编码变成字节流;同时,它也支持流中对象图形的互补重构造。序列化用于轻型持久性和借助于套接字或远程方法调用(RMI)进行的通信。序列化中现在包括一个 API(Application Programming Interface,应用程序接口),允许独立于类的域指定对象的序列化数据,并允许使用现有协议将序列化数据域写入流中或从流中读取,以确保与缺省读写机制的兼容性。

为编写应用程序,除多数瞬态应用程序外,都必须具备存储和检索 Java对象的能力。以序列化方式存储和检索对象的关键在于提供重新构造该对象所需的足够对象状态。存储到流的对象可能会支持 Serializable(可序列化)或 Externalizable(可外部化)接口。对于Java对象,序列化形式必须能标识和校验存储其内容的对象所属的 Java类,并且将该内容还原为新的实例。对于可序列化对象,流将提供足够的信息将流的域还原为类的兼容版本。对于可外部化对象,类将全权负责其内容的外部格式。序列化 Java 对象的目的是:提供一种简单但可扩充的机制,以序列化方式维护 Java对象的类型及安全属性;具有支持编组和解编的扩展能力以满足远程对象的需要;具有可扩展性以支持 Java 对象的简单持久性;只有在自定义时,才需对每个类提供序列化自实现;允许对象定义其外部格式。

三、分布式应用的实现和运行步骤

编写Java RMI分布式应用程序的步骤主要包括以下几步:

(1) 将远程类的功能定义为Java接口。在Java中,远程对象是实现远程接口的类的实例。在远程接口中声明每个要远程调用的方法。远程接口具有如下特点:1) 远程接口必须声明为public。如果不这样,则除非客户端与远程接口在同一个包内,否则当试图装入实现该远程接口的远程对象时会得到错误结果。2) 远程对象扩展java.rmi.Remote接口。3) 除了所有应用程序特定的例外之外,每个方法还必须抛出java.rmi.RemoteException例外。4) 任何作为参数或返回值传送的远程对象的数据类型必须声明为远程接口类型,而不是实现类。

(2) 编写和实现服务器类。该类是实现(1)中定义的远程接口。所以在该类中至少要声明实现一个远程接口,并且必须具有构造方法。在该类中还要实现远程接口中所声明的各个远程方法。

(3) 编写使用远程服务的客户机程序。在该类中使用java.rmi.Naming中的lookup()方法获得对远程对象的引用,依据需要调用该引用的远程方法,其调用方式和对本地对象方法的调用相同。

实现了服务器和客户机的程序后,就是编译和运行该RMI系统。其步骤有:
(1) 使用javac编译远程接口类,远程接口实现类和客户机程序。
(2) 使用rmic编译器生成实现类的stub和skeleton。
(3) 启动RMI注册服务程序rmiregistry。
(4) 启动服务器端程序。
(5) 启动客户机程序。

|
hehe:碰巧,今天我做了一个这方面的程序,共享给你:)
分别编译下面的.java文件,生成.class
rmic RMI_AddImpl 分别生成 RMI_AddImpl_Skel.class,RMI_AddImpl_Stub.class
服务器端包括程序:服务器端类,接口,存根和骨架类。
客户端程序:客户端类,接口,存根类。
运行时:服务器端:rmiregistry、java Rmi_AddServer
客户端:java Rmi_AddClient
在windows2000 Jdk1.4.1_01下通过!
//RMI_Add.java
public interface RMI_Add extends java.rmi.Remote {
public long add(long a, long b,long c)
throws java.rmi.RemoteException;
}
//RMI_AddImpl.java
public class RMI_AddImpl extends
java.rmi.server.UnicastRemoteObject
implements RMI_Add{ public RMI_AddImpl()
throws java.rmi.RemoteException {
super();
}
public long add(long a, long b,long c )
throws java.rmi.RemoteException {
return a + b+ c;
}
}
//RMI_AddServer.java
import java.rmi.Naming;
public class RMI_AddServer {
public RMI_AddServer() {
try {
RMI_Add d = new RMI_AddImpl();
Naming.rebind("rmi://10.7.3.168:1099/RMI_AddService", d);
} catch (Exception e) { }
}
public static void main(String args[]) {
new RMI_AddServer();
}
}
//RMI_AddClient.java
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.net.MalformedURLException;
import java.rmi.NotBoundException;
public class RMI_AddClient {
public static void main(String[] args) {
try {
RMI_Add d = (RMI_Add)Naming.lookup("rmi://localhost/RMI_AddService");
System.out.println("the result of 3+4+5 is:");
System.out.println( d.add(3, 4,5) );
}
catch (Exception e){
System.out.print("hheee,something wrong");
}
}
}

    
 
 

您可能感兴趣的文章:

 
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 请高手帮忙解释一下,insmod ./$module.ko || exit 1中的“||”是什么意思啊,多谢!
  • C++ STL Bitsets构造函数及成员函数解释及代码示例
  • classpath里的.;到底有什么用?能解释解释吗?
  • CentOS安装Telnet,以root用户登陆Telnet以及CentOS的各种终端解释
  • 请问java的xml解释器有哪些?怎么能在applet里用这些解释器?
  • 大虾们给我解释解释这个输出问题。这里小弟先谢了。
  • 实在是不能理解,谁能帮我解释解释!
  • 能不能帮我解释解释什么是EJB?
  • 关于"symbol lookup error"问题的诡异现象,高手帮忙解释解释
  • alex 解释器 alexinterpreter
  • 地震解释软件系统 OpendTect
  • 请教高人来解释一下小弟关于poll()函数的疑惑
  • Java源代码解释器 Beanshell
  • 这个"."怎么解释?
  • 高手帮忙解释
  • 请详细解释javamail里的“收件人类型”的CC,TO,BCC的意义???
  • linux中/dev下都是些什么文件啊?大侠们谁可以帮我解释一下?
  • 多线程的例子。但是不知道为什么看不懂。唉,笨:(各们帮帮忙了给我解释解释
  • 数字电视CA卡解释模块 OSCam
  • markdonw解释器 sundown
  • Brainfuck编译器和JIT解释器 bfc
  • Scheme Lisp 解释器 Subs


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3