发表于: 2017-10-05 22:35:34

1 739


今天完成的事情:

RMI

远程方法调用(RMI)顾名思义是一台机器上的程序调用另一台机器上的方法。RMI是Java支撑分布式系统的基石,RMI是远程过程调用(RPC)的一种面向对象实现,RMI底层是通过socket通信和对象序列化技术来实现的。

RMI的目的就是要使运行在不同的计算机中的对象之间的调用表现得像本地调用一样。RMI 应用程序通常包括两个独立的程序:服务器程序和客户机程序。RMI 需要将行为的定义与行为的实现分别定义, 并允许将行为定义代码与行为实现代码存放并运行在不同的 JVM 上。在 RMI 中, 远程服务的定义是存放在继承了 Remote 的接口中。远程服务的实现代码存放在实现该定义接口的类中。RMI 支持两个类实现一个相同的远程服务接口: 一个类实现行为并运行在服务器上, 而另一个类作为一个远程服务的代理运行在客户机上。客户程序发出关于代理对象的调用方法, RMI 将该调用请求发送到远程 JVM 上, 并且进一步发送到实现的方法中。实现方法将结果发送给代理, 再通过代理将结果返回给调用者。

当客户端调用远程对象方法时, 存根负责把要调用的远程对象方法的方法名及其参数编组打包,并将该包向下经远程引用层、传输层转发给远程对象所在的服务器。通过 RMI 系统的 RMI 注册表实现的简单服务器名字服务, 可定位远程对象所在的服务器。该包到达服务器后, 向上经远程引用层, 被远程对象的 Skeleton 接收, 此 Skeleton 解析客户包中的方法名及编组的参数后, 在服务器端执行客户要调用的远程对象方法, 然后将该方法的返回值( 或产生的异常) 打包后通过相反路线返回给客户端, 客户端的 Stub 将返回结果解析后传递给客户程序。事实上, 不仅客户端程序可以通过存根调用服务器端的远程对象的方法, 而服务器端的程序亦可通过由客户端传递的远程接口回调客户端的远程对象方法。在分布式系统中, 所有的计算机可以是服务器, 同时又可以是客户机。

Remote 接口用于标识其方法可以从非本地虚拟机上调用的接口。任何远程对象都必须直接或间接实现此接口。只有在“远程接口”(扩展 java.rmi.Remote 的接口)中指定的这些方法才可远程使用。 也就是说需要远程调用的方法必须在扩展Remote接口的接口中声名并且要抛出RemoteException异常才能被远程调用。远程对象必须实现java.rmi.server.UniCastRemoteObject类,这样才能保证客户端访问获得远程对象时。

写了一个简单的Demo

远程接口定义:

package com.rmi;

import java.rmi.Remote;
import java.rmi.RemoteException;

/**
* created by 姚远 on 2017/10/5.
*/
public interface HelloDefine extends Remote {
public String helloWorld() throws RemoteException;

   public String sayHello(String name) throws RemoteException;
}

远程接口实现:

package com.rmi;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

/**
* created by 姚远 on 2017/10/5.
*/
public class HelloDefineImp extends UnicastRemoteObject implements HelloDefine {
/**
    *
    */
   private static final long serialVersionUID = 1L;

   public HelloDefineImp() throws RemoteException {
super();
   }

public String helloWorld() throws RemoteException {
return "Hello AlphaGo!";
   }

public String sayHello(String name) throws RemoteException {
return "Hello" + name +"!";
   }

}

服务端:

package com.rmi;

import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

/**
* created by 姚远 on 2017/10/5.
*/
public class HelloServer {
HelloDefine hello;

   public void server() throws RemoteException, MalformedURLException, AlreadyBoundException {
hello = new HelloDefineImp();

       //远程对象注册表实例
       LocateRegistry.createRegistry(8888);
       //把远程对象注册到RMI注册服务器上
       Naming.bind("rmi://localhost:8888/Hello", hello);
       System.out.println("server:对象绑定成功!");
   }
}

客户端:

package com.rmi;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

/**
* created by 姚远 on 2017/10/5.
*/
public class HelloClient {
public HelloDefine hello;

   public void client() throws MalformedURLException, RemoteException, NotBoundException {
//在RMI注册表中查找指定对象
       hello = (HelloDefine) Naming.lookup("rmi://localhost:8888/Hello");
       //调用远程对象方法
       System.out.println("client:");
       System.out.println(hello.helloWorld());
       System.out.println(hello.sayHello("神之一手"));
   }
}

测试:

package com.rmi;

import org.junit.Test;

import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

/**
* created by 姚远 on 2017/10/5.
*/
public class RMITest {
@Test
   public void testServer() throws RemoteException, MalformedURLException, AlreadyBoundException {
HelloServer server = new HelloServer();
       server.server();
       while(true);
   }

@Test
   public void testClient() throws MalformedURLException, RemoteException, NotBoundException {
HelloClient client = new HelloClient();
       client.client();
   }
}

单独运行客户端是不行的

先启动服务端,再启动客户端

明天计划的事情:

拆分任务7的server和client,整合rmi



返回列表 返回列表
评论

    分享到