RMI:远程方法调用(Remote Method Invocation)

扩展:RPC与RMI的区别

  1:方法调用方式不同:

   RMI中是通过在客户端的Stub对象作为远程接口进行远程方法的调用每个远程方法都具有方法签名。如果一个方法在服务器上执行,但是没有相匹配的签名被添加到这个远程接口(stub)上,那么这个新方法就不能被RMI客户方所调用

    RPC中是通过网络服务协议向远程主机发送请求,请求包含了一个参数集和一个文本值,通常形成“classname.methodname(参数集)”的形式。RPC远程主机就去搜索与之相匹配的类和方法,找到后就执行方法并把结果编码,通过网络协议发回。

    2:适用语言范围不同:

     RMI只用于Java;

     RPC是网络服务协议,与操作系统和语言无关。

    3:调用结果的返回形式不同:

      Java是面向对象的,所以RMI的调用结果可以是对象类型或者基本数据类型;

      RMI的结果统一由外部数据表示 (External Data Representation, XDR) 语言表示,这种语言抽象了字节序类和数据类型结构之间的差异。

 

RMI代码示例:

Config.java

package shenzhou;

public class Client {
private String name;
private String hostURL;
private String obj;
public Client(String name){
this.name = name;
hostURL = "rmi://" + Config.SERVER_IP + ":" + Config.PORT + "/";
this.obj = Config.OBJECT_NAME;
}
public void callRMethod(){
try{
RMethod rm = (RMethod) java.rmi.Naming.lookup(hostURL + obj);
String result = rm.sayHello(name);
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Client c1 = new Client("Monica");
c1.callRMethod();
Client c2 = new Client("Joy");
c2.callRMethod();
Client c3 = new Client("Ross");
c3.callRMethod();
Client c4 = new Client("Chandler");
c4.callRMethod();
}
}

RMethod.java
package shenzhou;

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

public interface RMethod extends Remote {
String sayHello(String name) throws RemoteException;
}

RMethodImpl.java
package shenzhou;

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

public class RMethodImpl extends UnicastRemoteObject implements RMethod {

protected RMethodImpl() throws RemoteException {
super();
// TODO Auto-generated constructor stub
}

@Override
public String sayHello(String name) throws RemoteException {
// TODO Auto-generated method stub
System.out.println("Client-" + name + ": invoking \" sayHello \"");
return "Hello " + name + "\n this is a message from Remote Method";
}

}

Client.java
package shenzhou;

public class Client {
private String name;
private String hostURL;
private String obj;
public Client(String name){
this.name = name;
hostURL = "rmi://" + Config.SERVER_IP + ":" + Config.PORT + "/";
this.obj = Config.OBJECT_NAME;
}
public void callRMethod(){
try{
RMethod rm = (RMethod) java.rmi.Naming.lookup(hostURL + obj);
String result = rm.sayHello(name);
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Client c1 = new Client("Monica");
c1.callRMethod();
Client c2 = new Client("Joy");
c2.callRMethod();
Client c3 = new Client("Ross");
c3.callRMethod();
Client c4 = new Client("Chandler");
c4.callRMethod();
}
}

Server.java
package shenzhou;

import java.rmi.RMISecurityManager;
import java.rmi.registry.LocateRegistry;

public class Server {

public static void main(String[] args) {
new Server();
}

public Server() {
if (null == System.getSecurityManager()) {
System.setSecurityManager(new RMISecurityManager());
}
try {
try {
LocateRegistry.createRegistry(Config.PORT);
} catch (java.rmi.server.ExportException ex) {
System.out.println("Register the port failed:\n" + ex.getMessage());
}
RMethod rm = new RMethodImpl();
String objAddr = "rmi://" + Config.SERVER_IP
+ ":" + Config.PORT
+ "/" + Config.OBJECT_NAME;
java.rmi.Naming.rebind(objAddr, rm);
System.out.println("Server is running...");
} catch (Exception e) {
System.out.println("Server startup failed!");
e.printStackTrace();
}
}

}

小结:Server端:rebind 绑定(url + 调用对象);
    Client端:lookup 根据 url 获取远程调用

作用:使用本地方法一样调用远程方法
 
 


 
posted on 2018-08-21 14:12  一中晴哥威武  阅读(1208)  评论(0编辑  收藏  举报