RMI (Remote Method Invocation)
1,RMI 采用stubs 和 skeletons 来进行远程对象(remote object)的通讯。stub 充当远程对象的客户端代理,有着和远程对象相同的远程接口,远程对象的调用实际是通过调用该对象的客户端代理对象stub来完成的。
2,RMI目前使用Java远程消息交换协议JRMP(Java Remote Messaging Protocol)进行通信。由于JRMP是专为Java对象制定的,Java RMI具有Java的"Write Once,Run Anywhere"的优点,是分布式应用系统的百分之百纯Java解决方案。
3,RMI一般都是同步的,也就是说,当client调用Server的一个方法的时候,需要等到对方的返回,才能继续执行client端,这个过程调用本地方法感觉上是一样的,这也是RMI的一个特点。
4,RMI采用其分布式垃圾收集功能收集不再被网络中任何客户程序所引用的远程服务对象。与Java 虚拟机内部的垃圾收集类似,分布式垃圾收集功能允许用户根据自己的需要定义服务器对象,并且明确这些对象在不再被客户机引用时会被删除。 点击打开链接
客户端代码
1,RMI 采用stubs 和 skeletons 来进行远程对象(remote object)的通讯。stub 充当远程对象的客户端代理,有着和远程对象相同的远程接口,远程对象的调用实际是通过调用该对象的客户端代理对象stub来完成的。
2,RMI目前使用Java远程消息交换协议JRMP(Java Remote Messaging Protocol)进行通信。由于JRMP是专为Java对象制定的,Java RMI具有Java的"Write Once,Run Anywhere"的优点,是分布式应用系统的百分之百纯Java解决方案。
3,RMI一般都是同步的,也就是说,当client调用Server的一个方法的时候,需要等到对方的返回,才能继续执行client端,这个过程调用本地方法感觉上是一样的,这也是RMI的一个特点。
4,RMI采用其分布式垃圾收集功能收集不再被网络中任何客户程序所引用的远程服务对象。与Java 虚拟机内部的垃圾收集类似,分布式垃圾收集功能允许用户根据自己的需要定义服务器对象,并且明确这些对象在不再被客户机引用时会被删除。 点击打开链接
5,RMI是java独有得基于不同网络节点上的java虚拟机之间的java对象之间的相互调用,RMI使用TCP/IP协议传输java对象,用RMI传输数据需要将对象实例化,因为不同java虚拟机之间java对象无法共享,所以采用序列化来进行对象之间的数据交互。RMI是面向对象方式的javaRPC。
服务端程序
package com.halfworlders.rmi;
import java.rmi.Remote;
public interface ICompute extends Remote {
//接口的所有方法都必须抛出RemoteException以说明该方法是有风险的
public int plus(int a, int b)throws java.rmi.RemoteException;
}
package com.halfworlders.rmi;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface IFileUtil extends Remote {
public byte[] downloadFile(String fileName) throws RemoteException;
}
package com.halfworlders.rmi;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class ComputeImpl extends UnicastRemoteObject implements ICompute {
//继承类的构造函数必须也抛出RemoteException
protected ComputeImpl() throws RemoteException {
super();
}
private static final long serialVersionUID = -2021048048711929262L;
//由于方法参数与返回值最终都将在网络上传输,故必须是可序列化的
public int plus(int a, int b)throws java.rmi.RemoteException{
return a+b;
}
}
package com.halfworlders.rmi;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class FileUtilImpl extends UnicastRemoteObject implements IFileUtil {
protected FileUtilImpl() throws RemoteException {
super();
}
private static final long serialVersionUID = 7594622080290821912L;
public byte[] downloadFile(String fileName) throws RemoteException {
File file = new File(fileName);
byte buffer[] = new byte[(int) file.length()];
int size = buffer.length;
System.out.println("download file size = " + size + "b");
if (size > 1024 * 1024 * 10) {// 限制文件大小不能超过10M,文件太大可能导制内存溢出!
throw new RemoteException("Error:<The File is too big!>");
}
try {
BufferedInputStream input = new BufferedInputStream(
new FileInputStream(fileName));
input.read(buffer, 0, buffer.length);
input.close();
System.out.println("Info:<downloadFile() hed execute successful!>");
return buffer;
} catch (Exception e) {
System.out.println("FileUtilImpl: " + e.getMessage());
e.printStackTrace();
return null;
}
}
}
package com.halfworlders.rmi;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
public class RMITestMain {
public static void main(String[] args) throws RemoteException, MalformedURLException {
ICompute compute = new ComputeImpl();
IFileUtil fileUtil = new FileUtilImpl();
LocateRegistry.createRegistry(1099); //加上此程序,就可以不要在控制台上开启RMI的注册程序,1099是RMI服务监视的默认端口
Naming.rebind("rmi://localhost:1099/compute", compute);
Naming.rebind("rmi://localhost:1099/fileUtil", fileUtil);
System.out.print("Ready");
}
}
客户端代码
package com.halfworlders.rmi;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
public class ComputeClient {
public static void main(String[] args) throws MalformedURLException, RemoteException, NotBoundException {
ICompute compute = (ICompute) Naming.lookup("rmi://localhost:1099/compute");
System.out.println(compute.plus(2, 3));
}
}
package com.halfworlders.rmi;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
public class FileUtilClient {
public static void main(String args[]) throws IOException, NotBoundException {
String name = "rmi://localhost:1099/fileUtil";
IFileUtil fileUtil = (IFileUtil) Naming.lookup(name);
byte[] filedata = fileUtil.downloadFile("d://san.png");
if (filedata == null) {
System.out.println("Error:<filedata is null!>");
System.exit(0);
}
File file = new File("e://san.png");
System.out.println("file.getAbsolutePath() = " + file.getAbsolutePath());
BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(file.getAbsolutePath()));
output.write(filedata, 0, filedata.length);
output.flush();
output.close();
System.out.println("~~~~~End~~~~~");
}
}