我花了很多时间试图解决这个问题,但我似乎一无所获。根据我的研究,使用RMI似乎是一个经常出现的问题。基本上,我有服务器和客户端,并且客户端和服务器之间的通信是通过RMI对象完成的。
这是客户端的代码
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client{
static private RMIDecoder rmi_name = new RMIDecoder();
private static Registry registry;
private static Communication stub;
private Client() {}
public static void main(String args[]){
try {
int port = 1099 + rmi_name.getId(args[0]);
registry = LocateRegistry.getRegistry(port);
stub = (Communication) registry.lookup(args[0]); //object name as argument
if(args[1].equals("BACKUP")){
System.out.println(stub.backup(args[2],Integer.parseInt(args[3])));
}
else {
System.out.println(stub.restore(args[2]));
}
} catch (Exception e){
System.err.println("Client exception: " + e.toString());
e.printStackTrace();
}
}
}
这是服务器的代码
public class Server implements Communication {
static private Hashtable<String,ChunkInfo> file_info = new Hashtable<>();
static private RMIDecoder rmi_name = new RMIDecoder();
static private Multicastsocket mc = null;
static private DatagramSocket mdb = null;
static private Multicastsocket mdr = null;
static private String server_id;
static private FileHandler file_handler = new FileHandler();
static private Utils utility = new Utils();
static private Network network = new Network();
private static Registry registry;
private static Communication stub;
public Server(){
mc = network.initiateMC();
mdb = network.initiateMDB();
mdr = network.initiateMDR();
new File(".\\PEER" + server_id).mkdir();
}
//COMMUNICATION INTERFACE FUNCTIONS IMPLEMENTATION
public String backup(String filename,int repDegree){
storeInfo(filename);
Thread backup = new Thread(new BackupInit(filename,repDegree,server_id));
backup.start();
return "Backing up " + filename;
}
public String restore(String filename){
Thread restore = new Thread(new RestoreInit(filename,file_info.get(filename),server_id));
restore.run();
return filename + " has been restored successfully.";
}
public static void main(String args[]){
server_id = args[0];
Thread mc_listener = new Thread(new MCListener(mc,server_id));
Thread mdb_listener = new Thread(new MDBListener(server_id));
mc_listener.start();
mdb_listener.start();
try{
Server obj = new Server();
stub = (Communication) UnicastRemoteObject.exportObject(obj,0);
//Bind the remote object's stub in the registry
int port = 1098 + Integer.parseInt(args[0]);
registry = LocateRegistry.createRegistry(port);
registry.bind(rmi_name.getName(Integer.parseInt(args[0]) - 1),stub);
}
catch (Exception e){
e.printStackTrace();
}
}
private void storeInfo(String filename){
String fileId = file_handler.getFileId(filename);
double totalChunkNr = file_handler.getNumberOfChunks(filename);
ChunkInfo chunkInfo = new ChunkInfo(fileId);
chunkInfo.setTotalChunks(totalChunkNr);
file_info.put(filename,chunkInfo);
}
}
我的交流界面
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Communication extends Remote{
String backup(String filename,int repDegree) throws RemoteException;
String restore(String filename) throws RemoteException;
}
最后我创建了一个名为RMIDecoder的类
import java.util.Vector;
public class RMIDecoder {
static Vector<String> rmi_name = new Vector<>();
public RMIDecoder(){
fillRMITable();
}
void fillRMITable(){
rmi_name.add("alpha");
rmi_name.add("bravo");
rmi_name.add("charlie");
rmi_name.add("delta");
rmi_name.add("echo");
rmi_name.add("foxtrot");
}
String getName(int index){
return rmi_name.elementAt(index);
}
int getId(String name){
return rmi_name.indexOf(name);
}
}
因此,基本上我启动了六台服务器,每台服务器都作为“ java Server x”,其中x是服务器的数字ID。每个id都有一个将用于rmi对象名称的名称(它遵循北约注音字母,alpha表示1,bravo表示2,等等)。在Server类中使用唯一的端口和相应的名称创建注册表。在Client类中,我改用getRegistry,因为我已经准备通过RMI与之通信的服务器。该客户端称为“ java客户端name_of_rmi_obj ...”,其中name_of_rmi_obj可以为alpha / bravo / charlie等。
现在的问题是,启动这六个服务器并尝试在客户端执行某些操作后,其中一些将失败,即,尝试与特定服务器通信时会引发标题中的Exception。不能正常工作的服务器并不总是相同的,有时只是其中的两个,有时不是,有时几乎是全部。
从我所阅读的内容中,确保所使用的存根和注册表都是静态变量和类变量非常重要,这样它们就不会被垃圾收集器接收,因此我也这样做了。 我相信这里的代码足以解决我的问题,但是如果我无法显示任何内容,请告诉我。谢谢。