Berkeley Algorithm
BerkeleyInterface:
import java.rmi.*;
public interface BerkeleyInterface extends Remote {
void sendClientTime(String clientId, long clientTime) throws RemoteException;
void updateTime(long newTime) throws RemoteException;
long getTime() throws RemoteException;
}
BerkeleyServer:
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
import java.time.*;
import java.util.*;
public class BerkeleyServer extends UnicastRemoteObject implements BerkeleyInterface {
private Map<String, Long> clientTimes = new HashMap<>();
private long serverTime;
public BerkeleyServer() throws RemoteException {
serverTime = System.currentTimeMillis();
System.out.println("Initial Server Time: " + formatTime(serverTime));
}
@Override
public synchronized void sendClientTime(String clientId, long clientTime) throws
RemoteException {
clientTimes.put(clientId, clientTime);
System.out.println("Client [" + clientId + "] time received: " + formatTime(clientTime));
if (clientTimes.size() == 2) { // Wait for 2 clients
long total = serverTime;
for (long t : clientTimes.values()) {
total += t;
}
long average = total / (clientTimes.size() + 1); // +1 for server
long offset = average - serverTime;
serverTime = average;
System.out.println("\n[Server Time Updated]");
System.out.println("New Server Time (ms): " + serverTime);
System.out.println("Adjusted DateTime: " + formatTime(serverTime));
clientTimes.clear(); // Ready for next round
}
}
@Override
public void updateTime(long newTime) throws RemoteException {
this.serverTime = newTime;
}
@Override
public long getTime() throws RemoteException {
return serverTime;
}
private String formatTime(long millis) {
return Instant.ofEpochMilli(millis)
.atZone(ZoneId.systemDefault())
.toLocalDateTime()
.toString();
}
public static void main(String[] args) {
try {
BerkeleyServer server = new BerkeleyServer();
LocateRegistry.createRegistry(1099);
Naming.rebind("BerkeleyService", server);
System.out.println("Berkeley Server is running...");
} catch (Exception e) {
e.printStackTrace();
}
}
}
BerkeleyClient:
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
public class BerkeleyClient extends UnicastRemoteObject implements BerkeleyInterface {
public BerkeleyClient() throws RemoteException {}
@Override
public void sendClientTime(String clientId, long time) throws RemoteException {}
@Override
public void updateTime(long newTime) throws RemoteException {}
@Override
public long getTime() throws RemoteException {
return System.currentTimeMillis();
}
public static void main(String[] args) {
try {
Scanner sc = new Scanner(System.in);
BerkeleyInterface server = (BerkeleyInterface)
Naming.lookup("rmi://localhost/BerkeleyService");
String clientId = UUID.randomUUID().toString().substring(0, 8);
System.out.print("Enter your current system time in milliseconds: ");
long clientTime = sc.nextLong();
server.sendClientTime(clientId, clientTime);
System.out.println("Client [" + clientId + "] sent time successfully.");
} catch (Exception e) {
System.out.println("Error: " + e);
}
}
}
output: