之所以要做该实验,主要是为了完成分布式系统的作业,但是由于老师上课讲的不是很详细,很多地方不是很明白。本实验主要参考来自于http://www.blogjava.net/fanyingjie/archive/2011/09/24/359401.html,但是该文档中有些地方不是很明确,在郭大侠的帮助下,经历些小波折终于完成了实验,在实验过程中,我明白了么爷为什么将写过的设计整理出来,因为,有些东西你用完之后,很快就会丢掉,这样一点收获也没有,真的只是为了应付作业,这样没有任何意义。
下面详细介绍下实现过程,附图详解。
首先简单了解下RMI。
RMI(Remote Method Invocation)
RMI应用通常包含两个独立的程序——一个服务端程序和一个客户端程序。典型的服务端程序创建一些远程对象,并且使得这些远程对象的引用是可访问的,等待客户端程序调用这些对象上的方法。而一个典型的客户端程序包含一个服务器上的一个或多个远程对象是的远程引用,然后调用这些远程对象上的方法。RMI提供一个这样的机制使得客户端和服务端程序可以沟通和来回传递信息。这样的应用被称为分布式对象应用。
分布式对象应用需要实现以下3点:
•定位远程对象。应用程序可以使用不同的机制来获得对远程对象的引用。例如,一个应用程序可以通过RMI的简单的命名设施、RMI注册表注册它的远程对象。另外,应用程序可以传递和返回远程对象引用其他远程调用的一部分。
•与远程对象沟通。远程对象之间的通信的细节是由RMI处理的。对于程序员,远程通信看起来类似于普通的Java方法调用。
•为传递的对象加载类定义。因为RMI使对象可以来回传递,它提供了机制使得对象的类定义加载又可以实现数据传输。
1、新建一个Java Project(ds——你可以理解为屌丝,因为本程序确实蛮屌丝的,至少我是这样认为的),在该项目中新建一个demo.rmi的package,再在package下创建一个Echo接口,一个EchoServer类,一个EchoClient类。
具体代码如下:
Echo接口
package demo.rmi; import java.rmi.*; public interface Echo extends Remote { String echo(String msg) throws RemoteException; }
实现EchoServer类
package demo.rmi; import java.net.*; import java.rmi.*; import java.rmi.registry.*; import java.rmi.server.*;
public class EchoServer extends UnicastRemoteObject implements Echo { //默认构件器,也要“掷”出RemoteException违例 public EchoServer() throws RemoteException { super();
} public String echo(String msg) throws RemoteException { return "Echo: " + msg; } public static void main(String [] args) throws RemoteException { /*创建和安装一个安全管理器,令其支持RMI。作为Java开发包的一部分,适用于RMI唯一一个是RMISecurityManager.*/ //在程序内部创建一个LocateRegistry,并将自身注册到该LocateRegistry,其中的数值8111表示LocateRegistry运行的端口。 Registry r = LocateRegistry.createRegistry(8106); try { /*创建远程对象的一个或多个实例,下面是EchoServer对象*/ EchoServer es = new EchoServer(); /*向RMI远程对象注册表注册至少一个远程对象。一个远程对象拥有的方法即可生成指向其他远程对象的句柄,这样,客户到注册表里访问一次,得到第一个远程对象即可.*/ r.rebind("EchoServer", es); System.out.println("Ready to provide echo service..."); } catch (Exception e) { e.printStackTrace(); } } }
实现EchoClient类
package demo.rmi; import java.text.SimpleDateFormat; import java.util.Calendar; import java.rmi.*; import java.rmi.registry.*; public class EchoClient { public static void main(String [] args) throws RemoteException { try { Registry r = LocateRegistry.getRegistry("localhost", 8106); Echo e = (Echo)r.lookup("EchoServer"); String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime()); System.out.println(e.echo(time)); } catch (Exception e) { e.printStackTrace(); }
} }
到这步,程序编写的任务差不多结束了,下面就是一些在dos下的命令执行。
注意:在此之前一定要对程序存根,在eclipse编译时会出现错过,不过不要紧,在文件夹ds\src\demo\rmi下添加一个txt格式的Policy文件。
文件内容如下:
grant {
permission java.security.AllPermission "", "";
};
理由:之前说到的编译错误,java.security.AccessControlException: access denied (java.net.SocketPermission 127.0.0.1:1099 connect,resolve)
原因很简单,RMI Server/Client程序试图通过Socket连接访问本机的rmiregistry服务(即RMI的Naming Service,其运行的默认端口是1099)。
准备工作完成。
DOS运行
编译java文件
命令:javac *.java
rmic编译实现类,产生_Stub类
在demo.rmi.EchoServer.java上级目录下运行如下命令:
rmic demo.rmi.EchoServer
执行EchoServer终端
命令:java demo.rmi.EchoServer
再另外开启一个dos终端
执行EchoClient终端
命令:java demo.rmi.EchoClient
最终结果:
对于RMI还不是很了解,不过大致有了些概念。