RMI 概述
RMI(Remote Method Invocation)是一种执行远程调用的Java API。RMI的目的是使在不同计算机上运行的对象(Object)之间的调用行为类似于本地调用。
在RMI机制中,服务器(Server)应实现一定的功能并将其注册到注册表(Registry)中,客户端(Client)应在注册表的命名空间(Naming space)中获取对象
RMI 细节
当机器A上的代码想要调用驻留在机器B上的远程对象时,始终有两个中间对象实际处理通信:存根(stub object)和骨架(skeleton object)。
存根(stub)对象位于机器A中,必须:
构建一个信息块(information block),该信息块包括
要使用的远程对象的标识符(identifier),
描述要调用的方法的操作号(operation number)
骨架对象位于机器B中,其任务是
要解组(unmarshal)参数,
要在服务器上的真实对象上调用所需的方法,
要捕获服务器上调用的返回值或异常(exception),
要将包含封送格式(marshalled form)的值的返回给客户机上的存根。
RMI简单实验
一台电脑调用不同电脑上的‘获取随机数方法’,并把获得的随机数加和。
效果:
机器间连接:
Client中Getregistry() 使用给定的localhost、端口号(19999)在本地创建一个存根对象(stub object)作为注册表远程对象的代理
Server中用 createRegistry() 绑定相同的端口。用Rebind() 使用名称绑定自己。这样就可以在RMI注册表中注册远程对象。
实验拓扑结构:
JAVA代码
HelloClient.java
import java.rmi.*;
import java.rmi.registry.*;
import java.net.InetAddress;
public class HelloClient {
public static void main(String[] args) {
int num1 = (int)(Math.random()*100);
int result = 0;
String text = "rmi work";
HelloInterface rmi = null;
try {
Registry registry = LocateRegistry.getRegistry("192.168.128.21", 19999);
rmi = (HelloInterface) registry.lookup("server");
System.out.println("Connected to Server");
} catch (Exception e) {
e.printStackTrace();
}
try {
InetAddress address = InetAddress.getLocalHost();
rmi.sendAddress(address);
} catch (Exception e) {
System.out.println("ERROR: Could not create the registry.");
e.printStackTrace();
}
if (rmi != null) {
try {
System.out.println(rmi.getMessage(text));
result = rmi.sum(num1, rmi.getMessage(text));
rmi.sendMessage(Integer.toString(num1));
rmi.setSum(result);
rmi.printSum();
} catch (RemoteException e) {
e.printStackTrace();
}
System.out.println("Finished");
}
}
}
HelloServer.java
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.net.InetAddress;
public class HelloServer implements HelloInterface {
private int sum;
@Override
public int sum(int num1, int num2) throws RemoteException {
return num1+num2;
}
@Override
public String say() throws RemoteException {
return "message";
}
@Override
public void sendMessage(String s) throws RemoteException {
System.out.println(s);
}
@Override
public void sendAddress(InetAddress address) throws RemoteException {
System.out.println(address);
}
@Override
public int getMessage(String text) throws RemoteException {
return sum;
}
@Override
public void setSum(int result) throws RemoteException {
sum = result;
}
@Override
public void printSum() throws RemoteException {
System.out.println("sum: " + Integer.toString(sum));
}
public static void main(String[] args) {
int sum = 0;
Registry reg = null;
try {
reg = LocateRegistry.createRegistry(19999);
InetAddress address = InetAddress.getLocalHost();
System.out.println("DCS Starter:" + address);
} catch (Exception e) {
System.out.println("ERROR: Could not create the registry.");
e.printStackTrace();
}
HelloServer serverObject = new HelloServer();
try {
reg.rebind("server", (HelloInterface) UnicastRemoteObject.exportObject(serverObject, 0));
} catch (Exception e) {
System.out.println("ERROR: Failed to register the server object.");
e.printStackTrace();
}
}
}
HelloInterface.java
import java.rmi.*;
import java.net.InetAddress;
public interface HelloInterface extends Remote {
public String say() throws RemoteException;
public void sendMessage(String text) throws RemoteException;
public void setSum(int result) throws RemoteException;
public int getMessage(String text) throws RemoteException;
public int sum(int num1, int num2) throws RemoteException;
public void sendAddress(InetAddress address) throws RemoteException;
public void printSum() throws RemoteException;
}