Why use RMI
In this project, I thought of many ways to communicate between the client and the server. Since I was working on a rich client application, I finally selected the technology between RMI and Java-sockets. Among them, RMI The flexibility is not high. Both the client and the server must be written in Java, but it is more convenient to use. On the other hand, java-sockets, although more flexible, needs to define the communication protocol between the server and the client. It’s quite troublesome. After weighing it several times, I finally chose RMI for server-client communication.
File upload problem
In the process of using java-rmi, you will inevitably encounter a file upload problem. Since file streams cannot be transmitted in rmi (for example, the method parameters in rmi cannot be FileInputStream and the like), then we have to choose a compromise. The best way is to first use FileInputStream to read the file into a Byte array, then pass this Byte array as a parameter into the RMI method, and then restore the Byte array to an outputStream on the server side, so that it can be passed through RMI Let’s transfer files
This also has the disadvantage that the accuracy of the transmitted data cannot be verified.
Let me explain it with an example below.
FileClient
Copy the code code as follows:
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();
}
}
//This method is more important. Through this method, a file named filename is converted into a byte array.
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{
//The filename here should be the address where the file is stored on the server side
public void upload(String filename, byte[] file) throws RemoteException;
}
FileDataService_imp
Copy the code code as follows:
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
Copy the code code as follows:
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();
}
}