Я потратил довольно много времени, пытаясь решить эту проблему, и, похоже, я ничего не получил. Из моего исследования, кажется, что это повторяющаяся проблема при использовании 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 - это цифра c id сервера. У каждого идентификатора есть имя, которое он будет использовать для имени объекта rmi (оно следует из алфавита phoneti c НАТО, альфа для 1, браво для 2 и т. Д. c.). Реестр создается в классе Server с уникальным портом и соответствующим именем. В классе Client вместо этого я использую getRegistry, поскольку предполагается, что сервер, с которым я буду общаться через RMI, уже создан. Клиент называется «java Client name_of_rmi_obj ...», где name_of_rmi_obj может быть альфа / bravo / charl ie et c ..
Теперь проблема в том, что после запуска этих шести серверов и при попытке что-то сделать на стороне клиента, некоторые из них потерпят неудачу, то есть исключение в заголовке выдается при попытке установить связь с определенным сервером. Не работающие серверы не всегда одинаковы, иногда их всего два, иногда нет, иногда почти все.
Из того, что я прочитал, важно убедиться, что как используемые заглушки, так и реестр являются stati c и переменными класса, поэтому сборщик мусора не подхватывает их, поэтому я тоже это сделал. Я считаю, что приведенного здесь кода достаточно, чтобы раскрыть мою проблему, но если я не смог что-то показать, пожалуйста, дайте мне знать. Спасибо.