My First RMI Program

本文详细介绍如何使用Java RMI(远程方法调用)构建分布式应用程序。包括接口定义、接口实现、服务器端与客户端程序的编写及运行流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RMI,远程方法调用(Remote Method Invocation)是 Enterprise JavaBeans 的支柱,是建立分布式Java 应用程序的方便途径。RMI是非常容易使用的,但是它非常的强大。

  RMI 的基础是接口,RMI 构架基于一个重要的原理:定义接口和定义接口的具体实现是分开的。下面我们通过具体的例子,建立一个简单的远程计算服务和使用它的客户程序

  一个正常工作的 RMI 系统由下面几个部分组成:

  ● 远程服务的接口定义

  ● 远程服务接口的具体实现

  ● 桩(Stub)和框架(Skeleton)文件

  ● 一个运行远程服务的服务器

  ● 一个 RMI 命名服务,它允许客户端去发现这个远程服务

  ● 类文件的提供者(一个 HTTP 或者 FTP 服务器)

  ● 一个需要这个远程服务的客户端程序

  下面我们一步一步建立一个简单的 RMI 系统。首先在你的机器里建立一个新的文件夹,以便放置我们创建的文件,为了简单起见,我们只使用一个文件夹存放客户端和服务端代码,并且在同一个目录下运行服务端和客户端。

  如果所有的 RMI 文件都已经设计好了,那么你需要下面的几个步骤去生成你的系统:

  1、 编写并且编译接口的 Java 代码

  2、 编写并且编译接口实现的 Java 代码

  3、 从接口实现类中生成桩(Stub)和框架(Skeleton)类文件

  4、 编写远程服务的主运行程序

  5、 编写 RMI 的客户端程序

  6、 安装并且运行 RMI 系统

一 、 接口

 远程对象的本地接口声明(RMIOperate.java) 

· 该类仅仅是一个接口声明,RMI客户机可以直接使用它,RMI服务器必须通过一个远程对象来实现它,并用某个专有的URL注册它的一个实例。

· 远程接口扩展 java.rmi.Remote 接口。
· 除了所有应用程序特定的例外之外,每个方法还必须在 throws 子句中声明 java.rmi.RemoteException(或 RemoteException 的父类)。
/*
 */
import java.rmi.*;
// RMI本地接口必须从Remote接口派生
public interface Hello extends Remote {
   
// 接口中的具体方法声明,注意必须声明抛出RemoteException
    String helloWorld(String message) throws RemoteException;
}
二、 接口的具体实现
    这个类应实现RMI客户机调用的远程服务对象的本地接口,它必须从UnicastRemoteObject继承,构造函数应抛出RemoteException异常。
import java.rmi.*;
import javax.rmi.PortableRemoteObject;
public class HelloImpl extends PortableRemoteObject implements Hello {
    /* 构造函数 */
    public HelloImpl() throws RemoteException {
        super();
    }
    /* 实现本地接口中声明的'helloWorld()'方法 */
    public String helloWorld(String message) throws RemoteException {
        System.out.println("我在RMI的服务器端,客户端正在调用'sayHello'方法。 ");
        System.out.println("Hello  " + message);
        return message;
    }
}

三、RMI服务器类
    该类创建远程对象实现类HelloImpl的一个实例,然后通过一个专有的URL来注册它。所谓注册就是通过Java.rmi.Naming.bind()方法或Java.rmi.Naming.rebind()方法,将HelloImpl实例绑定到指定的URL上。
import java.rmi.*;
public class HelloServer {
    public static void main(String[] args) {  
        try {
            System.out.println("开始 RMI Server ...");
            /* 创建远程对象的实现实例 */
            HelloImpl hImpl = new HelloImpl();
            System.out.println("将实例注册到专有的URL ");
            Naming.rebind("HelloService", hImpl);
           
            System.out.println("等待RMI客户端调用...");
            System.out.println("");
        } catch (Exception e) {
            System.out.println("错误: " + e);
        }
    }
}

请注意有关 rebind 方法调用的下列参数:

  • 第一个参数是 URL 格式的 java.lang.String,表示远程对象的位置和名字。
    • 需要将 myhost 的值更改为服务器名或 IP 地址。否则,如果在 URL 中省略,则主机缺省值为当前主机,而且在 URL 中无需指定协议(例如“HelloServer”)。
    • 在 URL 中,可以选择提供端口号:例如“//myhost:1234/HelloServer”。端口缺省值为 1099。除非服务器在缺省 1099 端口上创建注册服务程序,否则需要指定端口号。
  • 第二个参数为从中调用远程方法的对象实现引用。
  • RMI 运行时将用对远程对象 stub 程序的引用代替由 hImpl 参数指定的实际远程对象引用。远程实现对象(如 HelloImpl 实例)将始终不离开创建它们的虚拟机。因此,当客户机在服务器的远程对象注册服务程序中执行查找时,将返回包含该实现的 stub 程序的对象。
四、RMI客户机类

· RMI客户使用java.rmi.Naming.lookup()方法,在指定的远程主机上查找RMI服务对象,若找到就把它转换成本地接口RMIOperate类型。它与CORBA不同之处在于RMI客户机必须知道提供RMI服务主机的URL,这个URL可以通过rmi://host/path或rmi://host:port/path来指定,如果省略端口号,就默认使用1099。
· Java.rmi.Naming.lookup()方法可能产生三个异常:Java.rmi.RemoteException、Java.rmi.NotBoundException、java.net. MalformedURLException,三个异常都需要捕获。
import java.rmi.*;
public class HelloClient {
    public static void main(String[] args) {
        //   在服务器端设置安全机制        
        /*
           if (System.getSecurityManager() == null) {
               System.setSecurityManager(new RMISecurityManager());
           }
        */    
        /* 默认为本地主机和默认端口 */
        String host = "localhost:1099";
        /* 带输入参数时,将host设置为指定主机 */
        if (args.length > 0)
            host = args[0];
        try {
            /* 根据指定的URL定位远程实现对象 */
            /* “h”是一个标识符,我们将用它指向实现“Hello”接口的远程对象 */
            Hello h = (Hello) Naming.lookup("rmi://" + host + "/HelloService");
           
            System.out.println("实现“Hello”接口的远程对象: " + h);
            System.out.println("我在客户端,开始调用RMI服务器端的'sayHello'方法");
            System.out.println("欢迎,  " + h.helloWorld("javamxj blog"));
        } catch (Exception ex) {
            System.out.println("错误 " + ex);
        }
    }
}
五、 编译代码与运行系统:
在MS-DOS环境下,创建一个D:/RMISample目录,把上面4个文件复制到这个目录下,然后在此目录下新建两个文件夹:client和server(把它们分别看作是客户端与服务端)。
(1).编译所有的源代码
D:/RMISample> javac *.java
(2).生成客户端存根和服务器框架
D:/RMISample> rmic HelloImpl
这将生成HelloImpl_Stub.class和HelloImpl_Skel.class。
:如果需要查看这两个类的源代码,可以使用“ rmic -keep HelloImpl”语句)
(3).把Hello.class、HelloClient.class、HelloImpl_Stub.class复制到client目录;
把Hello.class、HelloServer.class、HelloImpl_Skel.class、HelloImpl_Stub.class 复制到server目录。
(4).启动RMI注册
D:/RMISample/server>rmiregistry
(注: 我是在命令控制台下运行这个系统的,必须开启三个控制台窗口,一个运行RMIRegistry,一个运行服务器,还有一个运行客户端。)
(5).运行和调用

● 在服务器上执行HelloServer
D:/RMISample/server>java HelloServer
● 在本地客户机上运行HelloClient
D:/RMISample/client>java HelloClient
● 在远程客户机上运行HelloClient(须指明RMI服务器主机名或IP地址)
java HelloClient 222.222.34.34
运行rmiregistry和server后的结果:
再运行Client后的结果:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值