LAB RECORD
FOR
Distributed Systems
(CDS3001)
Submitted by:
Aditya Sachin Khamitkar
Registration Number: 22MIP10006
Slot: F11+F12
Submitted to:
Dr. Velmurugan L
School of Computing Science and Artificial Intelligence (SCAI)
Winter Semester 2024-2025
VIT Bhopal University
Index
1 Implement Non-token Based Algorithm for Mutual Exclusion 2
2 Implement Lamport2̆019s Logical Clock 6
3 Remote Procedure Call (RPC) to Transfer a File 9
4 Chat Server 11
5 Termination Detection 13
6 CORBA using C++ and Java as Two Ends 15
7 Implement Locking Algorithm 17
8 Implement Remote Method Invocation 20
1
Chapter 1
Implement Non-token Based
Algorithm for Mutual Exclusion
Aim
To implement a non-token based algorithm for mutual exclusion using Lamport’s algo-
rithm, ensuring that only one process can enter its critical section at a time without using
any physical token.
Requirements
• Java Development Kit (JDK)
• Java IDE such as IntelliJ IDEA or Eclipse
• Multi-threading and socket programming knowledge
• Understanding of logical clocks in distributed systems
• Multiple terminal support to simulate distributed processes
Theory
In a distributed system, mutual exclusion ensures that no two processes execute their
critical sections simultaneously. Lamport’s algorithm uses logical timestamps and mes-
sage passing to achieve mutual exclusion without using a physical token. Each request
is timestamped, and a process enters the critical section only when it has the earliest
request and all other processes have acknowledged its request.
2
Lab Manual - Distributed Systems
Lamport’s mutual exclusion algorithm satisfies the following conditions:
• Safety: At most one process can execute in the critical section at any time.
• Fairness: Requests are granted in the order of their timestamps.
• Liveness: Every request will eventually be granted.
Procedure
1. Each process maintains a logical clock which increments with each event.
2. When a process wants to enter its critical section, it sends a timestamped request
to all other processes.
3. Upon receiving a request, each process compares the timestamp with its own.
4. A process enters its critical section only after receiving replies from all other pro-
cesses.
5. After exiting the critical section, the process sends a release message to all others.
Code
1 import java . util .*;
2
3 class LamportMutex {
4 int pid ;
5 int clock ;
6 PriorityQueue < Request > requestQueue = new PriorityQueue < >(( a ,
b ) -> a . timestamp - b . timestamp ) ;
7
8 static class Request {
9 int pid , timestamp ;
10 Request ( int pid , int timestamp ) {
11 this . pid = pid ;
12 this . timestamp = timestamp ;
13 }
14 }
15
16 LamportMutex ( int pid ) {
17 this . pid = pid ;
18 this . clock = 0;
19 }
20
21 void requestCS () {
3
Lab Manual - Distributed Systems
22 clock ++;
23 Request req = new Request ( pid , clock ) ;
24 requestQueue . add ( req ) ;
25 broadcast ( " REQUEST " , req ) ;
26 }
27
28 void receive ( String type , Request req ) {
29 clock = Math . max ( clock , req . timestamp ) + 1;
30 if ( type . equals ( " REQUEST " ) ) {
31 requestQueue . add ( req ) ;
32 send ( " REPLY " , req . pid ) ;
33 } else if ( type . equals ( " RELEASE " ) ) {
34 requestQueue . removeIf ( r -> r . pid == req . pid ) ;
35 }
36 }
37
38 void releaseCS () {
39 requestQueue . removeIf ( r -> r . pid == pid ) ;
40 broadcast ( " RELEASE " , new Request ( pid , clock ) ) ;
41 }
42
43 void broadcast ( String type , Request req ) {
44 System . out . println ( type + " sent by P " + pid + " at " +
clock ) ;
45 }
46
47 void send ( String type , int toPid ) {
48 System . out . println ( type + " sent to P " + toPid ) ;
49 }
50 }
Listing 1.1: Lamport’s Mutual Exclusion in Java
Sample Output
REQUEST sent by P1 at 1
REPLY sent to P1
P1 enters critical section
RELEASE sent by P1 at 2
P1 exits critical section
Result/Outcome
The Lamport-based mutual exclusion algorithm is successfully implemented using Java.
It simulates message passing and timestamp ordering for entering and exiting the critical
4
Lab Manual - Distributed Systems
section.
Conclusion
This experiment demonstrates the implementation of mutual exclusion in distributed
systems without relying on a token. Logical clocks and message ordering ensure fairness
and safety in accessing critical resources.
5
Chapter 2
Implement Lamport2̆019s Logical
Clock
Aim
To implement Lamport2̆019s Logical Clock mechanism to track the order of events in a
distributed system.
Requirements
• Java Development Kit (JDK)
• Java IDE
• Concepts of logical clocks and causality
Theory
Lamport’s Logical Clock is used to assign a sequence of events in a distributed system
where physical time is not synchronized. Each process maintains a local counter incre-
mented for every event, and messages carry timestamps that help synchronize events
across the system.
6
Lab Manual - Distributed Systems
Procedure
1. Each process starts with a logical clock initialized to zero.
2. The clock is incremented before each event.
3. When a message is sent, the current clock value is sent with it.
4. On receiving a message, the receiver updates its clock: max(local, received) + 1.
Code
1 class Logi c a lC l o ck P r oc e s s {
2 int clock = 0;
3 int pid ;
4
5 Logic a lC l o ck P r oc e s s ( int pid ) {
6 this . pid = pid ;
7 }
8
9 void internalEvent () {
10 clock ++;
11 System . out . println ( " Internal event at P " + pid + " with
clock " + clock ) ;
12 }
13
14 void sendEvent () {
15 clock ++;
16 System . out . println ( " Send event from P " + pid + " with
clock " + clock ) ;
17 }
18
19 void receiveEvent ( int receivedClock ) {
20 clock = Math . max ( clock , receivedClock ) + 1;
21 System . out . println ( " Receive event at P " + pid + " with
updated clock " + clock ) ;
22 }
23 }
Sample Output
Send event from P1 with clock 1
Receive event at P2 with updated clock 2
Internal event at P2 with clock 3
7
Lab Manual - Distributed Systems
Result/Outcome
The logical clock implementation maintains a consistent order of events across distributed
processes.
Conclusion
Lamport2̆019s Logical Clock provides a simple mechanism for ordering events in a dis-
tributed system without relying on physical time synchronization.
8
Chapter 3
Remote Procedure Call (RPC) to
Transfer a File
Aim
To implement Remote Procedure Call (RPC) in Java to transfer a file from client to
server.
Requirements
• Java SDK
• Java RMI or Socket Programming (for simulation of RPC)
• Basic file handling knowledge
Theory
RPC enables a program to cause a subroutine to execute in another address space. In
Java, we can simulate RPC using RMI or socket programming. The client reads a file
and sends its content to the server.
Code (Socket based RPC simulation)
1 // Server . java
2 import java . io .*;
9
Lab Manual - Distributed Systems
3 import java . net .*;
4
5 public class Server {
6 public static void main ( String [] args ) throws IOException {
7 ServerSocket ss = new ServerSocket (5000) ;
8 Socket s = ss . accept () ;
9 DataInputStream dis = new DataInputStream ( s .
getInputStream () ) ;
10 FileOutputStream fos = new FileOutputStream ( " received . txt
");
11 int c ;
12 while (( c = dis . read () ) != -1) fos . write ( c ) ;
13 fos . close () ;
14 dis . close () ;
15 s . close () ;
16 ss . close () ;
17 }
18 }
19
20 // Client . java
21 import java . io .*;
22 import java . net .*;
23
24 public class Client {
25 public static void main ( String [] args ) throws IOException {
26 Socket s = new Socket ( " localhost " , 5000) ;
27 DataOutputStream dos = new DataOutputStream ( s .
getOutputStream () ) ;
28 FileInputStream fis = new FileInputStream ( " test . txt " ) ;
29 int c ;
30 while (( c = fis . read () ) != -1) dos . write ( c ) ;
31 fis . close () ;
32 dos . close () ;
33 s . close () ;
34 }
35 }
Conclusion
RPC allows invoking remote services. File transfer demonstrates RPC’s ability to abstract
remote interaction.
10
Chapter 4
Chat Server
Aim
To implement a simple chat server using Java.
Requirements
• Java SDK
• Socket programming knowledge
Theory
A chat server allows multiple clients to send and receive messages. It uses multithreading
to manage each client.
Code Overview
Due to complexity, simplified structure is shown:
1 // ChatServer . java
2 import java . io .*;
3 import java . net .*;
4 import java . util .*;
5
6 public class ChatServer {
11
Lab Manual - Distributed Systems
7 private static Set < Socket > clientSockets = new HashSet < >() ;
8
9 public static void main ( String [] args ) throws IOException {
10 ServerSocket server = new ServerSocket (1234) ;
11 while ( true ) {
12 Socket client = server . accept () ;
13 clientSockets . add ( client ) ;
14 new Thread (() -> handleClient ( client ) ) . start () ;
15 }
16 }
17
18 static void handleClient ( Socket client ) {
19 try {
20 BufferedReader in = new BufferedReader ( new
Inpu tStrea mReade r ( client . getInputStream () ) ) ;
21 String msg ;
22 while (( msg = in . readLine () ) != null ) {
23 for ( Socket s : clientSockets ) {
24 if ( s != client ) {
25 PrintWriter out = new PrintWriter ( s .
getOutputStream () , true ) ;
26 out . println ( msg ) ;
27 }
28 }
29 }
30 } catch ( IOException e ) { e . printStackTrace () ; }
31 }
32 }
Conclusion
The chat server showcases client-server architecture with concurrent client handling using
multithreading.
12
Chapter 5
Termination Detection
Aim
To implement a basic termination detection algorithm for a distributed system.
Theory
Termination detection ensures that a distributed computation has ended, and all pro-
cesses are idle with no messages in transit.
Code (Simplified Dijkstra-Scholten like)
1 class Node {
2 int id ;
3 boolean active = false ;
4
5 void performTask () {
6 active = true ;
7 System . out . println ( " Node " + id + " working ... " ) ;
8 try { Thread . sleep (1000) ; } catch ( Exception e ) {}
9 active = false ;
10 System . out . println ( " Node " + id + " finished . " ) ;
11 }
12
13 boolean isIdle () {
14 return ! active ;
15 }
16 }
13
Lab Manual - Distributed Systems
Conclusion
Termination detection is key to correctly halting distributed computations and reclaiming
resources.
14
Chapter 6
CORBA using C++ and Java as
Two Ends
Aim
To implement CORBA with one end in C++ and the other in Java for distributed object
communication.
Requirements
• Java ORB (like JacORB)
• C++ CORBA implementation (like TAO or omniORB)
• IDL compiler
Theory
CORBA (Common Object Request Broker Architecture) allows applications written in
different languages and platforms to communicate. IDL is used to define interfaces. Stubs
and skeletons are generated to handle communication.
Steps
1. Define an IDL file.
15
Lab Manual - Distributed Systems
2. Compile IDL to generate Java and C++ bindings.
3. Implement server in one language, client in another.
4. Run ORB and perform invocation.
IDL Example
1 interface Hello {
2 string sayHello () ;
3 };
Conclusion
CORBA enables seamless cross-language communication in distributed systems using
IDL and ORBs.
16
Chapter 7
Implement Locking Algorithm
Aim
To implement a distributed locking mechanism that allows safe access to shared resources.
Requirements
• Java Development Kit (JDK)
• Java multithreading knowledge
• Basic networking (optional)
Theory
Locking algorithms ensure only one process accesses a resource at a time. In a distributed
environment, locks are managed using either centralized, distributed, or quorum-based
approaches. Here, we implement a basic centralized lock server.
Procedure
1. A client process sends a lock request to the central lock manager.
2. If the lock is available, it is granted to the requester.
3. After completing its task, the client releases the lock.
17
Lab Manual - Distributed Systems
4. The lock manager then grants it to the next requester.
Code
1 class LockManager {
2 boolean locked = false ;
3 Queue < Integer > queue = new LinkedList < >() ;
4
5 synchronized void requestLock ( int pid ) {
6 System . out . println ( " P " + pid + " requesting lock " ) ;
7 if (! locked ) {
8 locked = true ;
9 System . out . println ( " Lock granted to P " + pid ) ;
10 } else {
11 queue . add ( pid ) ;
12 System . out . println ( " P " + pid + " added to queue " ) ;
13 }
14 }
15
16 synchronized void releaseLock ( int pid ) {
17 System . out . println ( " P " + pid + " releasing lock " ) ;
18 if (! queue . isEmpty () ) {
19 int next = queue . poll () ;
20 System . out . println ( " Lock granted to P " + next ) ;
21 } else {
22 locked = false ;
23 }
24 }
25 }
Sample Output
P1 requesting lock
Lock granted to P1
P2 requesting lock
P2 added to queue
P1 releasing lock
Lock granted to P2
18
Lab Manual - Distributed Systems
Result/Outcome
The lock manager successfully controls access to a shared resource, ensuring mutual
exclusion.
Conclusion
Centralized locking is a simple yet effective method for managing concurrent access in
distributed systems.
19
Chapter 8
Implement Remote Method
Invocation
Aim
To implement a basic Java program demonstrating Remote Method Invocation (RMI),
allowing a client to invoke methods on a remote server object.
Requirements
• JDK (Java Development Kit) 8 or above
• Text Editor or IDE (e.g., VS Code, IntelliJ IDEA, Eclipse)
• Command-line terminal or integrated terminal in IDE
Theory
Java Remote Method Invocation (RMI) is an API that allows objects to communicate
remotely. It enables an object running in one Java Virtual Machine (JVM) to invoke
methods on an object in another JVM.
The architecture includes:
• Remote Interface: Declares remote methods.
• Remote Object Implementation: Implements the remote interface and extends
UnicastRemoteObject.
20
Lab Manual - Distributed Systems
• Server: Registers the remote object in the RMI registry.
• Client: Looks up the remote object and invokes methods.
Procedure
Step 1: Create the Remote Interface
import java.rmi.*;
public interface Hello extends Remote {
String sayHello() throws RemoteException;
}
Step 2: Implement the Remote Interface
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RemoteException;
public class HelloImpl extends UnicastRemoteObject implements Hello {
public HelloImpl() throws RemoteException {
super();
}
public String sayHello() throws RemoteException {
return "Hello from the RMI server!";
}
}
Step 3: Create the Server
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Server {
public static void main(String[] args) {
try {
HelloImpl obj = new HelloImpl();
Registry registry = LocateRegistry.createRegistry(1099);
registry.rebind("Hello", obj);
System.out.println("Server is ready.");
21
Lab Manual - Distributed Systems
} catch (Exception e) {
System.out.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
}
Step 4: Create the Client
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client {
public static void main(String[] args) {
try {
Registry registry = LocateRegistry.getRegistry("localhost");
Hello stub = (Hello) registry.lookup("Hello");
String response = stub.sayHello();
System.out.println("Response from server: " + response);
} catch (Exception e) {
System.out.println("Client exception: " + e.toString());
e.printStackTrace();
}
}
}
Step 5: Compilation and Execution
1. Compile all Java files:
javac *.java
2. Start the server:
java Server
3. In a new terminal, run the client:
java Client
22
Lab Manual - Distributed Systems
Result
The client successfully invoked the remote method from the server and received the
message: "Hello from the RMI server!".
Conclusion
The experiment demonstrated a successful implementation of Java RMI. It enabled re-
mote communication between client and server through method invocation, showcasing
distributed computing capabilities in Java.
23