为什么要用RMI
在这次的项目中,对于客户端与服务器之间的通信,想了许多办法,由于做的是富客户端应用,最终将技术选定在了RMI和Java-sockets两种之间,其中RMI的灵活性不高,客户端和服务器端都必须是java编写,但使用比较方便,反观java-sockets,虽然比较灵活,但需要自己规定服务器端和客户端之间的通信协议。比较麻烦,几经权衡,最终还是选择RMI来进行服务器-客户端通信
文件上传问题
在使用java-rmi的过程中,必然会遇到一个文件上传的问题,由于在rmi中无法传输文件流(比如rmi中的方法参数不能是FileInputStream之类的),那么我们只好选择一种折中的办法,就是先用FileInputStream将文件读到一个 Byte数组中,然后把这个Byte数组作为参数传进RMI的方法中,然后在服务器端将Byte数组还原为outputStream,这样就能通过RMI 来传输文件了
这样做也有缺点,就是无法检验传输过来的数据的准确性,汗。。。
下面我就一个实例来讲解一下
文件结构
FileClient
package rmiupload;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
public class FileClient {
public FileClient() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
try {
FileDataService fileDataService = (FileDataService) Naming.lookup("rmi://localhost:9001/FileDataService");
fileDataService.upload("/Users/NeverDie/Documents/test.mp4", new FileClient().fileToByte("/Users/NeverDie/Music/test.mp4"));
} catch (MalformedURLException | RemoteException | NotBoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//这个方法比较重要,通过这个方法把一个名为filename的文件转化为一个byte数组
private byte[] fileToByte(String filename){
byte[] b = null;
try {
File file = new File(filename);
b = new byte[(int) file.length()];
BufferedInputStream is = new BufferedInputStream(new FileInputStream(file));
is.read(b);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return b;
}
}
FileDataService
package rmiupload;
import java.net.URL;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface FileDataService extends Remote{
//这里的filename应该是该文件存放在服务器端的地址
public void upload(String filename, byte[] file) throws RemoteException;
}
FileDataService_imp
package rmiupload;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.rmi.RemoteException;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.rmi.server.UnicastRemoteObject;
public class FileDataService_imp extends UnicastRemoteObject implements FileDataService{
public FileDataService_imp() throws RemoteException {
}
@Override
public void upload(String filename, byte[] fileContent) throws RemoteException{
File file = new File(filename);
try {
if (!file.exists())
file.createNewFile();
BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(file));
os.write(fileContent);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
; }
}
FileServer
package rmiupload;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
public class FileServer {
FileDataService fileDataService;
public FileServer() {
try {
fileDataService = new FileDataService_imp();
LocateRegistry.createRegistry(9001);
Naming.rebind("rmi://localhost:9001/FileDataService", fileDataService);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* @param args
*/
public static void main(String[] args) {
new FileServer();
}
}