Professional Documents
Culture Documents
Distributed System Lab Manual As On 5 Sept 2019
Distributed System Lab Manual As On 5 Sept 2019
C02• Design and develop distributed programs using sockets and RPC/RMI.
CO3 • Differentiate between different types of faults and fault handling techniques in order to
implement fault Tolerant systems
.
CO4• Analyze different algorithms and techniques for the design and development of distributed
Systems subject to specific design and performance constraints
.
Program List Prescribed by University
S. No. CO Programs
Course Incharge
Experiment List Prepared for this Session
S.No. Program Name Student Date Faculty Remark
Signature Signature
1 To Simulate
the
functioning of
Lamport’s
Logical clock
in ‘c’..
2 To Simulate
the
functioning of
Lamport’s
Vector clock
in ‘c’
3 To Simulate
the
Distributed
Mutual
exclusion in
‘c’.
4 To Simulate
the Non
Token based
algorithm-
Lamport’s
5 To Simulate
the Token
based
algorithm-
Raymond’s.
6 To Simulate
the
Distributed
Deadlock
Detection
algorithm-
Edge chasing.
7 To
Implement
‘Java RMI’
mechanism
for accessing
methods of
remote
systems.
8 To Simulate
balanced
sliding
Window
protocol in
‘c’.
9 To
implement a
distributed
chat server
using TCP
socket in C.
10 To
implement
CORBA
mechanism
by using C++
program at
one end and
Java Program
on the other.
Introduction
Distributed computing is a field of computer science that studies distributed systems.
A distributed system is a model in which components located on networked computers
communicate and coordinate their actions by passing messages. The components interact with
each other in order to achieve a common goal. Three significant characteristics of distributed
systems are: concurrency of components, lack of a global clock, and independent failure of
components. Examples of distributed systems vary from SOA-based systems to massively
multiplayer online games to peer-to-peer applications.
A computer program that runs in a distributed system is called a distributed program, and
distributed programming is the process of writing such programs. There are many alternatives
for the message passing mechanism, including pure HTTP, RPC-like connectors and message
queues.
A goal and challenge pursued by some computer scientists and practitioners in distributed
systems is location transparency; however, this goal has fallen out of favour in industry, as
distributed systems are different from conventional non-distributed systems, and the
differences, such as network partitions, partial system failures, and partial upgrades, cannot
simply be "papered over" by attempts at "transparency".
Experiment#1
Experiment Text: To Simulate the functioning of Lamport’s Logical clock in ‘c’
Outcome: Program will exhibit the simulation of Lamport’ logical clock behaviour based on
two rules.
What Student will learn? As discussed in class student will learn how this experiment can
decide happened before relation between any two event on same process and across the
processes.
Description: The "time" concept in distributed systems -- used to order events in a distributed
system.
Assumption:
Algorithm:
Ci is the local clock for process Pi
#include <stdio.h>
#include <stdlib.h>
void main()
{
Physical Clock 1
Process a has P.T.: 6
Process b has P.T.: 7
Physical Clock 2
Process c has P.T.: 2
Process d has P.T.: 3
What Student will learn? Student will be able to calculate happened before relationship even
for unrelated processes.
Description: Vector Clocks are used in distributed systems to determine whether pairs of
events are causally related. Using Vector Clocks, timestamps are generated for each event in
the system, and their causal relationship is determined by comparing those timestamps.
The timestamp for an event is an n-tuple of integers, where n is the number of processes.
Each process assigns a timestamp to each event. The timestamp is composed of that process
logical time and the last known time of every other process.
Algorithm:
ta < tb If and only if they meet two conditions:
1.They are not equal timestamps ( there exists i, ta[i] != tb[i]) and
2.each ta[i] is less than or equal to tb[i] (for all i, ta[i] <= tb[i])
Code:
#include<stdio.h>
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
long *p1(int i,long *comp);
long *p2(int i,long *comp);
long *p3(int i,long *comp);
void main()
{
long start[]={0,0,0},*vector;
clrscr();
while(!kbhit())
{
p1(1,&start[0]);
}
printf("\n Process Vector\n");
vector=p1(0,&start[0]);
printf("p1[%ld%ld%ld]\n",*vector,*(vector+1),*(vector+2));
vector=p2(0,&start[0]);
printf("p2[%ld%ld%ld]\n",*vector,*(vector+1),*(vector+2));
vector=p3(0,&start[0]);
printf("p3[%ld%ld%ld]\n",*vector,*(vector+1),*(vector+2));
}
long *p1(int i,long *comp)
{
static long a[]={0,0,0};
int next;
if(i==1)
{
a[0]++;
if(*(comp+1)>a[1])
a[1]=*(comp+1);
if(*(comp+2)>a[2])
a[2]=*(comp+2);
next=random(2);
if(next==0)
p2(1,&a[0]);
else if(next==1)
p3(1,&a[0]);
return(&a[0]);
}
else
return(&a[0]);
}
long *p2(int i,long *comp)
{
static long b[]={0,0,0};
int next;
if(i==1)
{
b[i]++;
if(*comp>b[0])
b[0]=*(comp);
if(*(comp+2)>b[2])
b[2]=*(comp+2);
next=random(2);
if(next==0)
p1(1,&b[0]);
else if(next==1)
p3(1,&b[0]);
return &b[0];
}
else
return &b[0];
}
long *p3(int i,long *comp)
{
static long c[]={0,0,0};
int next;
if(i==1)
{
c[2]++;
if(*comp>c[0])
c[0]=*(comp);
if(*(comp+1)>c[1])
c[1]=*(comp+1);
next=random(2);
if(next==0)
p1(1,&c[0]);
return &c[0];
}
else return &c[0];}
Expected Output:
What Student will learn? Student will learn how processes share resources on the basis of
mutual exclusion.
Algorithm:
Process 1: Request resource:
Resource Allocated No more requests process for this resource
Process2: Request Resource Denied
Process 1: Exit Resource:
Process2: Request Resource Allocated
Code:
#include<stdio.h>
#include<conio.h>
#include<dos.h>
#include<time.h>
void main()
{
int cs=0,pro=0; double run=5; char key='a'; time_t t1,t2;
clrscr();
printf("Press a key(except q) to enter a process into critical section."); printf(" \nPress
q at any time to exit.");
t1 = time(NULL) - 5; while(key!='q')
while(!kbhit())
if(cs!=0)
{
t2 = time(NULL);if(t2-t1 > run)
{
printf("Process%d ",pro-1);printf(" exits
critical section.\n");
cs=0;
}
}
key = getch(); if(key!='q')
{
if(cs!=0)
printf("Error: Another process is currently
executing critical section Please wait till its execution is
over.\n");
else
{
printf("Process %d ",pro);
printf(" entered critical section\n");
cs=1; pro++;
t1 = time(NULL);
}
}
}
}
Expected Output:
Press a key (except q) to enter a process into critical section. Press q at any time to exit.
or: Another process is currently executing critical section. Please wait till its execution
is over.
or: Another process is currently executing critical section. Please wait till its execution
is over.
What Student will learn? Student will learn the behaviour of Non-Token based algorithm for
mutual exclusion
Description: Requests for CS are executed in the increasing order of timestamps and time is
determined by logical clocks. Every site Si keeps a queue, request queuei , which contains mutual
exclusion requests ordered by their timestamps. This algorithm requires communication channels to
deliver messages the FIFO order.
Algorithm:
it broadcasts a REQUEST(tsi , i) message to all other sites and places the request on request queuei .
((tsi , i) denotes the timestamp of the request.)
places site Si ’s request on request queuej and it returns a timestamped REPLY message to Si .
Executing the critical section: Site Si enters the CS when the following two conditions hold:
L1: Si has received a message with timestamp larger than (tsi , i) from all other sites.
Code:
import java.util.*;
class lamport
int ts1,ts2,ts3,req1=0,req2=0,req3=0;
ts1=Integer.parseInt(sc.next());
System.out.print(“Enter Time Stamp for Site S2 :”);
ts2=Integer.parseInt(sc.next());
System.out.print(“Enter Time Stamp for Site S3 :”);
ts3=Integer.parseInt(sc.next());
System.out.print(“Is Site S1 Send a CS request : Y/N =”);
String res=sc.next();
if(res.equalsIgnoreCase(“y”))
req1=1;
req2=1;
req3=1;
q obj2=new q();
obj2.ts=ts2;
obj2.si=2;
q obj1=new q();
obj1.ts=ts1;
obj1.si=1;
q obj3=new q();
obj3.ts=ts3;
obj3.si=3;
q obj4=new q();
obj4.ts=ts3;
obj4.si=100;
if(req2==1)
l1.stack(obj2,obj1,1);
l2.stack(obj2,obj3,2);
}
lamport l3=new lamport();
if(req1==1)
l3.stack(obj1,obj2,1);
l4.stack(obj1,obj3,2);
if(req3==1)
l5.stack(obj3,obj1,1);
l6.stack(obj3,obj2,2);
if(req1==1)
System.out.println(“REQUEST(S1) :[ (“+obj1.a.ts+”,”+obj1.a.si+”)(“+obj1.b.ts+”,”+obj1.b.si+”)]”);
System.out.println(“REQUEST(S1) :[ (“+obj1.c.ts+”,”+obj1.c.si+”)(“+obj1.d.ts+”,”+obj1.d.si+”)]”); }
if(req2==1)
System.out.println(“REQUEST(S2) :[ (“+obj2.a.ts+”,”+obj2.a.si+”)(“+obj2.b.ts+”,”+obj2.b.si+”)]”);
System.out.println(“REQUEST(S2) :[ (“+obj2.c.ts+”,”+obj2.c.si+”)(“+obj2.d.ts+”,”+obj2.d.si+”)]”); }
if(req3==1)
System.out.println(“REQUEST(S3) :[ (“+obj3.a.ts+”,”+obj3.a.si+”)(“+obj3.b.ts+”,”+obj3.b.si+”)]”);
System.out.println(“REQUEST(S3) :[ (“+obj3.c.ts+”,”+obj3.c.si+”)(“+obj3.d.ts+”,”+obj3.d.si+”)]”); }
if((obj2.a.ts==obj2.c.ts)&&(obj2.a.si==obj2.c.si)&&(obj2.a.si==2))
l3.rel(obj2,obj1,1);
System.out.println(“REQUEST(S2) :[ (“+obj2.a.ts+”,”+obj2.a.si+”)]”);
System.out.println(“REQUEST(S2) :[ (“+obj2.c.ts+”,”+obj2.c.si+”)]”);
System.out.println(“REQUEST(S1) :[ (“+obj1.a.ts+”,”+obj1.a.si+”)(“+obj1.b.ts+”,”+obj1.b.si+”)]”);
System.out.println(“REQUEST(S1) :[ (“+obj1.c.ts+”,”+obj1.c.si+”)(“+obj1.d.ts+”,”+obj1.d.si+”)]”);
System.out.println(” SIte S1 Executing in CS “);
}}
if((objcal.ts)<(objcmp.ts
{
if(r==1)
objcal.a=objcal;
objcal.b=objcmp;
else
objcal.c=objcal;
objcal.d=objcmp;
else
{
if(r==1)
objcal.b=objcal;
objcal.a=objcmp;
else
objcal.d=objcal;
objcal.c=objcmp;
if(objcl.a.si==objrm.a.si)
if(rm==1)
objrm.a=objrm.b;
objrm.b=null;
else
objrm.c=objrm.d;
objrm.b=null;
}}
class q
int ts,si;
q a;
q b;
q c;
q d;
Expected Output: The process which would have next to on ring would access resource.
Description:
The mutual exclusion problem is an important problem in distributed systems. The fairness
property is a crucial attribute of distributed mutual exclusion algorithms. All solutions to the
distributed mutual exclusion problem are expected to implement at least starvation freedom
as the fairness criterion. In certain situations, a stronger fairness criterion is desirable. In this
paper, we have substantially modified Raymond's tree based distributed mutual exclusion
algorithm to incorporate such a fairness criterion, viz., the least executed criterion. The lower
and upper bounds on the number of messages generated per critical section execution are 0
and 2D respectively, where D is the diameter of a spanning tree of the distributed system.
These bounds are the same as those of Raymond's algorithm.
Algorithm:
Nodal Properties
1. Each node has only one parent to whom received requests are forwarded
2. Each node maintains a FIFO queue of requests each time that it sees the token;
3. If any node is forwarding privilege to other node and has non-empty queue then it
forwards a request message along
Algorithm
1. If a node i wish to receive the token in order to enter into its critical section, it sends a
request to its parent, node j.
If node j FIFO is empty, node j shifts i into the its FIFO queue; j then issues a
request to its parent, k, that it desires the token
If node j FIFO queue is not empty, it simply shifts i into the queue
2. When node j receives the token from k, it forwards the token to i and i is removed from
the queue of j
If the queue of j is not empty after forwarding the token to i, j must issue a request
to i in order to get the token back
Note: If j wishes to request a token, and its queue is not empty, then it places itself into its own
queue. Node j will utilize the token to enter into its critical section if it is at the head of the
queue when the token is received.
Description: The Java Remote Method Invocation (Java RMI) is a Java API that
performs remote method invocation, the object-oriented equivalent of remote procedure
calls (RPC), with support for direct transfer of serialized Java classes and distributed garbage
collection.
1. The original implementation depends on Java Virtual Machine (JVM) class representation
mechanisms and it thus only supports making calls from one JVM to another. The
protocol underlying this Java-only implementation is known as Java Remote Method
Protocol (JRMP).
2. In order to support code running in a non-JVM context, a CORBA version was later
developed.
Usage of the term RMI may denote solely the programming interface or may signify both the
API and JRMP, IIOP, or another implementation, whereas the term RMI-IIOP (read: RMI over
IIOP) specifically denotes the RMI interface delegating most of the functionality to the
supporting CORBA implementation.
The basic idea of Java RMI, the distributed garbage-collection (DGC) protocol, and much of the
architecture underlying the original Sun implementation, come from the 'network objects' feature
of Modula-3.
Code:
RMI SERVER:
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.registry.*;
public class RmiServer extends UnicastRemoteObject implements
RmiServerIntf {
public static final String MESSAGE = "Hello World";
//Instantiate RmiServer
INTERFACE
import java.rmi.Remote;
import java.rmi.RemoteException;
CLIENT
import java.rmi.Naming;
Expected Output: Client can access the method of given by server using interface
Description:
Conceptually, each portion of the transmission (packets in most data link layers, but bytes in
TCP) is assigned a unique consecutive sequence number, and the receiver uses the numbers to
place received packets in the correct order, discarding duplicate packets and identifying missing
ones. The problem with this is that there is no limit on the size of the sequence number that can
be required.
Algorithm:
The sequence numbers always obey the rule that na ≤ nr ≤ ns ≤ nt ≤ na + wt. That is:
na ≤ nr: The highest acknowledgement received by the transmitter cannot be higher than
the highest nr acknowledged by the receiver.
nr ≤ ns: The span of fully received packets cannot extend beyond the end of the partially
received packets.
ns ≤ nt: The highest packet received cannot be higher than the highest packet sent.
nt ≤ na + wt: The highest packet sent is limited by the highest acknowledgement received and
the transmit window size.
Transmitter operation
Whenever the transmitter has data to send, it may transmit up to wt packets ahead of the latest
acknowledgment na. That is, it may transmit packet number nt as long as nt <na+wt.
In the absence of a communication error, the transmitter soon receives an acknowledgment for
all the packets it has sent, leaving na equal to nt. If this does not happen after a reasonable delay,
the transmitter must retransmit the packets between na and nt.
Techniques for defining "reasonable delay" can be extremely elaborate, but they only affect
efficiency; the basic reliability of the sliding window protocol does not depend on the details.
Receiver operation
Every time a packet numbered x is received, the receiver checks to see if it falls in the receive
window, nr ≤ x < ns+wr. (The simplest receivers only have to keep track of one value nr=ns.) If it falls
within the window, the receiver accepts it. If it is numbered nr, the receive sequence number
is increased by 1, and possibly more if further consecutive packets were previously received and
stored. If x > nr, the packet is stored until all preceding packets have been received.[1] If x≥ns, the
latter is updated to ns=x+1.
If the packet's number is not within the receive window, the receiver discards it and does not
modify nr or ns.
Whether the packet was accepted or not, the receiver transmits an acknowledgment
containing the current nr. (The acknowledgment may also include information about additional
packets received between nr or ns, but that only helps efficiency.)
Note that there is no point having the receive window wr larger than the transmit window wt,
because there is no need to worry about receiving a packet that will never be transmitted; the
useful range is 1 ≤ wr ≤ wt.
Code:
1. slic.java
While(true)
{
Dout = d.readLine();
If(dout.equals(“quit”))
Break;
toserver.writeBytes(dout+’\n’);
din = fromserver.readLine();
System.out.println(“Server :”+din);
System.out.println(“\nEnter for server :”);
}
}
}
2. slis.java
while(true){
din = fromclient.readLine();
System.out.println(“\n client data:”+din);
System.out.println(“enter for client :”);
dout = d.readLine();
if(dout.equals(“quit”))
break;
toclient.writeBytes(dout+’\n’);
}
}
}
Expected Output: Demonstration of sliding window
What Student will learn? Lowest scalable possible behaviour of Distributed systems
Description: Sockets allow communication between two different processes on the same or
different machines. To be more precise, it's a way to talk to other computers using standard
Unix file descriptors. In Unix, every I/O action is done by writing or reading a file descriptor.
A file descriptor is just an integer associated with an open file and it can be a network
connection, a text file, a terminal, or something else.
To a programmer, a socket looks and behaves much like a low-level file descriptor. This is
because commands such as read() and write() work with sockets in the same way they do with
files and pipes.
Code:
SERVER
#include<stdio.h>
#include<netinet/in.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netdb.h>
#include<stdlib.h>
#include<string.h>
#define MAX 80
#define PORT 43454
#define SA struct sockaddr
void func(int sockfd)
{
char buff[MAX];
int n;
for(;;)
{
bzero(buff,MAX);
read(sockfd,buff,sizeof(buff));
printf("From client: %s\t To client : ",buff);
bzero(buff,MAX);
n=0;
while((buff[n++]=getchar())!='\n');
write(sockfd,buff,sizeof(buff));
if(strncmp("exit",buff,4)==0)
{
printf("Server Exit...\n");
break;
}
}
}
int main()
{
int sockfd,connfd,len;
struct sockaddr_in servaddr,cli;
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1)
{
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(PORT);
if((bind(sockfd,(SA*)&servaddr, sizeof(servaddr)))!=0)
{
printf("socket bind failed...\n");
exit(0);
}
else
printf("Socket successfully binded..\n");
if((listen(sockfd,5))!=0)
{
printf("Listen failed...\n");
exit(0);
}
else
printf("Server listening..\n");
len=sizeof(cli);
connfd=accept(sockfd,(SA *)&cli,&len);
if(connfd<0)
{
printf("server acccept failed...\n");
exit(0);
}
else
printf("server acccept the client...\n");
func(connfd);
close(sockfd);
}
CLIENT
#include<stdio.h>
#include<netinet/in.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netdb.h>
#include<string.h>
#include<stdlib.h>
#define MAX 80
#define PORT 43454
#define SA struct sockaddr
void func(int sockfd)
{
char buff[MAX];
int n;
for(;;)
{
bzero(buff,sizeof(buff));
printf("Enter the string : ");
n=0;
while((buff[n++]=getchar())!='\n');
write(sockfd,buff,sizeof(buff));
bzero(buff,sizeof(buff));
read(sockfd,buff,sizeof(buff));
printf("From Server : %s",buff);
if((strncmp(buff,"exit",4))==0)
{
printf("Client Exit...\n");
break;
}
}
}
int main()
{
int sockfd,connfd;
struct sockaddr_in servaddr,cli;
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1)
{
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_addr.s_addr=inet_addr("127.0.0.1");
servaddr.sin_port=htons(PORT);
if(connect(sockfd,(SA *)&servaddr,sizeof(servaddr))!=0)
{
printf("connection with the server failed...\n");
exit(0);
}
else
printf("connected to the server..\n");
func(sockfd);
close(sockfd);
}
Expected Output:
SERVER SIDE
$ cc tcpchatserver.c
$ ./a.out
Socket successfully created..
Socket successfully binded..
Server listening..
server acccept the client...
From client: hai
To client : hello
From client: exit
To client : exit
Server Exit...
$
CLIENT SIDE
$ cc tcpchatclient.c
$ ./a.out
Socket successfully created..
connected to the server..
Enter the string : hai
From Server : hello
Enter the string : exit
From Server : exit
Client Exit...
Applications:
Prerequisites:
Outcome:
Description:
Algorithm:
Code:
1.FileInterface.idl
interface FileInterface {
typedef sequence<octet> Data;
Data downloadFile(in string fileName);
};
Now, let's compile the FileInterface.idl and generate server-side skeletons. Using
the command:
2.FileServant.java
import java.io.*;
3.FileServer.java
import java.io.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
4.FileClient.java
import java.io.*;
import java.util.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
if(argv.length < 1) {
System.out.println("Usage: java FileClient filename");
}
1. D:\Test\RND\Java\CORBA>tnameserv
2. D:\ Test \RND\Java\CORBA>java FileServer
3. D:\ Test \RND\Java\CORBA>idlj -fclient FileInterface.idl
4. D:\ Test \RND\Java\CORBA>java FileClient hello.txt
Expected Output: