0% found this document useful (0 votes)
45 views

Distributed Systems Lab File

Uploaded by

gfhghjvb
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
45 views

Distributed Systems Lab File

Uploaded by

gfhghjvb
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 34

INDEX

Date of Date of
S.N Name of Experiment Signature
Experiment Submission
Simulate the functioning of
1 Lamport's Logical Clock in 'C'
Simulate the Distributed Mutual
2 Exclusion in 'C'.
Implement a Distributed Chat
3 Server using TCP Sockets in 'C'.
Implement RPC mechanism for a
4 file transfer across a network in 'C'
Implement 'Java RMI' mechanism
5 for accessing methods of remote
systems.
Simulate Balanced Sliding
6 Window Protocol in 'C'.
Implement CORBA mechanism by
7 using 'C+t' program at one end and
'Java program on the other.
Develop a client server application
8 which implements File Transfer
protocol.
Implement a client server
9 application which implements
Name Server.
Experiment - 1

Aim: Simulate the functioning of Lamport's Logical Clock in 'C'.

Introduction: Lamport’s Logical Clock was created by Leslie Lamport. It is a procedure to


determine the order of events occurring. It provides a basis for the more advanced Vector Clock
Algorithm. Due to the absence of a Global Clock in a Distributed Operating System Lamport
Logical Clock is needed.

Theory:
Algorithm:
• Happened before relation(->): a -> b, means ‘a’ happened before ‘b’.
• Logical Clock: The criteria for the logical clocks are:
o [C1]: Ci (a) < Ci(b), [ Ci -> Logical Clock, If ‘a’ happened before ‘b’, then time
of ‘a’ will be less than ‘b’ in a particular process. ]
o [C2]: Ci(a) < Cj(b), [ Clock value of Ci(a) is less than Cj(b) ]

Reference:
• Process: Pi
• Event: Eij, where i is the process in number and j: jth event in the ith process.
• tm: vector time span for message m.
• Ci vector clock associated with process Pi, the jth element is Ci[j] and contains Pi‘s
latest value for the current time in process Pj.
• d: drift time, generally d is 1.

Implementation Rules[IR]:
• [IR1]: If a -> b [‘a’ happened before ‘b’ within the same process]
then, Ci(b) =Ci(a) + d
• [IR2]: Cj = max(Cj, tm + d) [If there’s more number of processes, then tm =
value of Ci(a), Cj = max value between Cj and tm + d]

For Example:
• Take the starting value as 1, since it is the 1st event and there is no incoming
value at the starting point:
• e11 = 1
• e21 = 1
• The value of the next point will go on increasing by d (d = 1), if there is no
incoming value i.e., to follow [IR1].
• e12 = e11 + d = 1 + 1 = 2
• e13 = e12 + d = 2 + 1 = 3
• e14 = e13 + d = 3 + 1 = 4
• e15 = e14 + d = 4 + 1 = 5
• e16 = e15 + d = 5 + 1 = 6
• e22 = e21 + d = 1 + 1 = 2
• e24 = e23 + d = 3 + 1 = 4
• e26 = e25 + d = 6 + 1 = 7
• When there will be incoming value, then follow [IR2] i.e., take the maximum
value between Cj and Tm + d.
• e17 = max(7, 5) = 7, [e16 + d = 6 + 1 = 7, e24 + d = 4 + 1 = 5,
maximum among 7 and 5 is 7]
• e23 = max(3, 3) = 3, [e22 + d = 2 + 1 = 3, e12 + d = 2 + 1 = 3,
maximum among 3 and 3 is 3]
• e25 = max(5, 6) = 6, [e24 + 1 = 4 + 1 = 5, e15 + d = 5 + 1 = 6,
maximum among 5 and 6 is 6]

Limitation:
• In case of [IR1], if a -> b, then C(a) < C(b) -> true.
• In case of [IR2], if a -> b, then C(a) < C(b) -> May be true or may not be true.
Source Code:
#include <stdio.h>
int max1(int a, int b) {
if (a > b)
return a;
else
return b;
}
void display(int e1, int e2, int p1[5], int p2[3]) {
int i;
printf("\nThe time stamps of events in P1: ");
for (i = 0; i < e1; i++) {
printf("%d ", p1[i]);
}
printf("\nThe time stamps of events in P2: ");
for (i = 0; i < e2; i++) {
printf("%d ", p2[i]);
}
}
void lamportLogicalClock(int e1, int e2, int m[5][3]) {
int i, j, k, p1[e1], p2[e2];
for (i = 0; i < e1; i++)
p1[i] = i + 1;
for (i = 0; i < e2; i++)
p2[i] = i + 1;

for (i = 0; i < e2; i++)


printf("\te2%d", i + 1);

for (i = 0; i < e1; i++) {


printf("\n e1%d\t", i + 1);
for (j = 0; j < e2; j++)
printf("%d\t", m[i][j]);
}
for (i = 0; i < e1; i++) {
for (j = 0; j < e2; j++) {
if (m[i][j] == 1) {
p2[j] = max1(p2[j], p1[i] + 1);
for (k = j + 1; k < e2; k++)
p2[k] = p2[k - 1] + 1;
}
if (m[i][j] == -1) {
p1[i] = max1(p1[i], p2[j] + 1);
for (k = i + 1; k < e1; k++)
p1[k] = p1[k - 1] + 1;
}
}
}
display(e1, e2, p1, p2);
}
int main() {
int e1 = 5, e2 = 3, m[5][3];

m[0][0] = 0;
m[0][1] = 0;
m[0][2] = 0;
m[1][0] = 0;
m[1][1] = 0;
m[1][2] = 1;
m[2][0] = 0;
m[2][1] = 0;
m[2][2] = 0;
m[3][0] = 0;
m[3][1] = 0;
m[3][2] = 0;
m[4][0] = 0;
m[4][1] = -1;
m[4][2] = 0;
lamportLogicalClock(e1, e2, m);
return 0;
}

Output:
Experiment - 2

Aim: Simulate the Distributed Mutual Exclusion in 'C'.

Introduction: Mutual exclusion is a concurrency control property which is introduced to


prevent race conditions. It is the requirement that a process cannot enter its critical section
while another concurrent process is currently present or executing in its critical section i.e only
one process is allowed to execute the critical section at any given instance of time.

Theory:
Mutual exclusion in single computer system Vs. distributed system: In single computer system,
memory and other resources are shared between different processes. The status of shared
resources and the status of users is easily available in the shared memory so with the help of
shared variable (For example: Semaphores) mutual exclusion problem can be easily solved. In
Distributed systems, we neither have shared memory nor a common physical clock and there
for we can not solve mutual exclusion problem using shared variables. To eliminate the mutual
exclusion problem in distributed system approach based on message passing is used. A site in
distributed system do not have complete information of state of the system due to lack of shared
memory and a common physical clock.

Requirements of Mutual exclusion Algorithm:


• No Deadlock: Two or more site should not endlessly wait for any message that will
never arrive.
• No Starvation: Every site who wants to execute critical section should get an
opportunity to execute it in finite time. Any site should not wait indefinitely to execute
critical section while other site are repeatedly executing critical section.
• Fairness: Each site should get a fair chance to execute critical section. Any request
to execute critical section must be executed in the order they are made i.e Critical
section execution requests should be executed in the order of their arrival in the system.
• Fault Tolerance: In case of failure, it should be able to recognize it by itself in order
to continue functioning without any disruption.

Source 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);
}
}
}
}

Output:
Experiment - 3

Aim: Implement a Distributed Chat Server using TCP Sockets in 'C'.

Introduction: If we are creating a connection between client and server using TCP then it has
a few functionalities like, TCP is suited for applications that require high reliability, and
transmission time is relatively less critical. It is used by other protocols like HTTP, HTTPs,
FTP, SMTP, Telnet. TCP rearranges data packets in the order specified. There is absolute
guarantee that the data transferred remains intact and arrives in the same order in which it was
sent. TCP does Flow Control and requires three packets to set up a socket connection before
any user data can be sent. TCP handles reliability and congestion control. It also does error
checking and error recovery. Erroneous packets are retransmitted from the source to the
destination.

Theory:
The entire process can be broken down into the following steps:
The entire process can be broken down into following steps:
TCP Server –
1. using create(), Create TCP socket.
2. using bind(), Bind the socket to server address.
3. using listen(), put the server socket in a passive mode, where it waits for the client
to approach the server to make a connection
4. using accept(), At this point, connection is established between client and server,
and they are ready to transfer data.
5. Go back to Step 3.
TCP Client –
1. Create TCP socket.
2. connect newly created client socket to server.

Source Code:

TCP Server:
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define MAX 80
#define PORT 8080
#define SA struct sockaddr

void func(int connfd) {


char buff[MAX];
int n;
for (;;) {
bzero(buff, MAX);
read(connfd, buff, sizeof(buff));
printf("From client: %s\t To client : ", buff);
bzero(buff, MAX);
n = 0;
while ((buff[n++] = getchar()) != '\n');
write(connfd, 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 accept failed...\n");
exit(0);
} else
printf("server accept the client...\n");

func(connfd);
close(sockfd);
}
TCP Client
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <unistd.h>
#define MAX 80
#define PORT 8080
#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);
}

Output:

Server Side

Client Side
Experiment - 4

Aim: Implement RPC mechanism for a file transfer across a network in 'C'.

Introduction: RPC is an effective mechanism for building client-server systems that are
distributed. RPC enhances the power and ease of programming of the client/server computing
concept. It’s a protocol that allows one software to seek a service from another program on
another computer in a network without having to know about the network. The software that
makes the request is called a client, and the program that provides the service is called a server.

Theory: In distributed computing, a remote procedure call (RPC) is when a computer program
causes a procedure (subroutine) to execute in a different address space (commonly on another
computer on a shared network), which is coded as if it were a normal (local) procedure
call, without the programmer explicitly coding the details for the remote interaction. That is,
the programmer writes essentially the same code whether the subroutine is local to the
executing program, or remote. This is a form of client–server interaction (caller is client,
executor is server), typically implemented via a request–response message-passing system. In
the object-oriented programming paradigm, RPCs are represented by remote method
invocation (RMI). The RPC model implies a level of location transparency, namely that
calling procedures are largely the same whether they are local or remote, but usually they are
not identical, so local calls can be distinguished from remote calls. Remote calls are usually
orders of magnitude slower and less reliable than local calls, so distinguishing them is
important.

RPCs are a form of inter-process communication (IPC), in that different processes have
different address spaces: if on the same host machine, they have distinct virtual address spaces,
even though the physical address space is the same; while if they are on different hosts, the
physical address space is different. Many different (often incompatible) technologies have been
used to implement the concept.

Sequence of events
• The client calls the client stub. The call is a local procedure call, with parameters pushed
on to the stack in the normal way.
• The client stub packs the parameters into a message and makes a system call to send
the message. Packing the parameters is called marshalling.
• The client's local operating system sends the message from the client machine to the
server machine.
• The local operating system on the server machine passes the incoming packets to the
server stub.
• The server stub unpacks the parameters from the message. Unpacking the parameters
is called unmarshalling.
• Finally, the server stub calls the server procedure. The reply traces the same steps in
the reverse direction.
Source Code:

// server code for UDP socket programming


#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define IP_PROTOCOL 0
#define PORT_NO 15050
#define NET_BUF_SIZE 32
#define cipherKey 'S'
#define sendrecvflag 0
#define nofile "File Not Found!"
// function to clear buffer
void clearBuf(char * b) {
int i;
for (i = 0; i < NET_BUF_SIZE; i++) b[i] = '\0';
}
// function to encrypt
char Cipher(char ch) {
return ch ^ cipherKey;
} // function sending file
int sendFile(FILE * fp, char * buf, int s) {
int i, len;
if (fp == NULL) {
strcpy(buf, nofile);
len = strlen(nofile);
buf[len] = EOF;
for (i = 0; i <= len; i++) buf[i] = Cipher(buf[i]);
return 1;
}
char ch, ch2;
for (i = 0; i < s; i++) {
ch = fgetc(fp);
ch2 = Cipher(ch);
buf[i] = ch2;
if (ch == EOF) return 1;
}
return 0;
}
// driver code
int main() {
int sockfd, nBytes;
struct sockaddr_in addr_con;
int addrlen = sizeof(addr_con);
addr_con.sin_family = AF_INET;
addr_con.sin_port = htons(PORT_NO);
addr_con.sin_addr.s_addr = INADDR_ANY;
char net_buf[NET_BUF_SIZE];
FILE * fp;
// socket()
sockfd = socket(AF_INET, SOCK_DGRAM, IP_PROTOCOL);
if (sockfd < 0) printf("\nfile descriptor not received!!\n");
else printf("\nfile descriptor %d received\n", sockfd);
// bind()
if (bind(sockfd, (struct sockaddr * ) & addr_con, sizeof(addr_con)) == 0)
printf("\nSuccessfully binded!\n");
else printf("\nBinding Failed!\n");
while (1) {
printf("\nWaiting for file name...\n");
// receive file name
clearBuf(net_buf);
nBytes = recvfrom(sockfd, net_buf, NET_BUF_SIZE, sendrecvflag, (struct sockaddr * ) &
addr_con, & addrlen);
fp = fopen(net_buf, "r");
printf("\nFile Name Received: %s\n", net_buf);
if (fp == NULL) printf("\nFile open failed!\n");
else printf("\nFile Successfully opened!\n");
while (1) { // process
if (sendFile(fp, net_buf, NET_BUF_SIZE)) {
sendto(sockfd, net_buf, NET_BUF_SIZE, sendrecvflag, (struct sockaddr * ) &
addr_con, addrlen);
break;
} // send
sendto(sockfd, net_buf, NET_BUF_SIZE, sendrecvflag, (struct sockaddr * ) & addr_con,
addrlen);
clearBuf(net_buf);
}
if (fp != NULL) fclose(fp);
}
return 0;
}
// client code for UDP socket programming
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define IP_PROTOCOL 0
#define IP_ADDRESS "127.0.0.1"
// localhost
#define PORT_NO 15050
#define NET_BUF_SIZE 32
#define cipherKey 'S'
#define sendrecvflag 0
// function to clear buffer
void clearBuf(char * b) {
int i;
for (i = 0; i < NET_BUF_SIZE; i++) b[i] = '\0';
}
// function for decryption
char Cipher(char ch) {
return ch ^ cipherKey;
} // function to receive file
int recvFile(char * buf, int s) {
int i;
char ch;
for (i = 0; i < s; i++) {
ch = buf[i];
ch = Cipher(ch);
if (ch == EOF) return 1;
else printf("%c", ch);
}
return 0;
}
// driver code
int main() {
int sockfd, nBytes;
struct sockaddr_in addr_con;
int addrlen = sizeof(addr_con);
addr_con.sin_family = AF_INET;
addr_con.sin_port = htons(PORT_NO);
addr_con.sin_addr.s_addr = inet_addr(IP_ADDRESS);
char net_buf[NET_BUF_SIZE];
FILE * fp;
// socket()
sockfd = socket(AF_INET, SOCK_DGRAM, IP_PROTOCOL);
if (sockfd < 0) printf("\nfile descriptor not received!!\n");
else printf("\nfile descriptor %d received\n", sockfd);
while (1) {
printf("\nPlease enter file name to receive:\n");
scanf("%s", net_buf);
sendto(sockfd, net_buf, NET_BUF_SIZE, sendrecvflag, (struct sockaddr * ) & addr_con,
addrlen);
printf("\n---------Data Received---------\n");
while (1) {
// receive
clearBuf(net_buf);
nBytes = recvfrom(sockfd, net_buf, NET_BUF_SIZE, sendrecvflag, (struct sockaddr * )
& addr_con, & addrlen);
// process
if (recvFile(net_buf, NET_BUF_SIZE)) {
break;
}
}
printf("\n-------------------------------\n");
}
return 0;
}
Experiment - 5

Aim: Implement 'Java RMI' mechanism for accessing methods of remote systems.

Introduction: The Java Remote Method Invocation (Java RMI) is a Java API that performs
the object-oriented equivalent of remote procedure calls (RPC), with support for direct
transfer of serialized Java objects and distributed garbage collection. 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). 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, whereas the term RMI-IIOP (read: RMI over IIOP) denotes the RMI interface
delegating most of the functionality to the supporting CORBA implementation.

Theory:
Working of RMI: The communication between client and server is handled by using two
intermediate objects: Stub object (on client side) and Skeleton object (on server side).

Stub Object: The stub object on the client machine builds an information block and sends this
information to the server. The block consists of
• An identifier of the remote object to be used
• Method name which is to be invoked
• Parameters to the remote JVM Skeleton

Object: The skeleton object passes the request from the stub object to the remote object.
It performs following tasks
• It calls the desired method on the real object present on the server.
• It forwards the parameters received from the stub object to the method.

Source Code:

// Creating Remote interface for our application


import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Hello extends Remote {
void printMsg() throws RemoteException;
}
// Implementing the remote interface
public class ImplExample implements Hello {
// Implementing the interface method
public void printMsg() {
System.out.println("This is an example RMI program");
}
}
// Developing the Server Program
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class Server extends ImplExample {
public Server() {}
public static void main(String args[]) {
try {
// Instantiating the implementation
class ImplExample obj = new ImplExample();
// Exporting the object of implementation class
// (here we are exporting the remote object to the stub)
Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0);
// Binding the remote object (stub) in the registry
Registry registry = LocateRegistry.getRegistry();
registry.bind("Hello", stub);
System.err.println("Server ready");
} catch (Exception e) {

System.err.println("Server exception: " + e.toString());


e.printStackTrace();
}
}
}

// Developing the Client Program


import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client {
private Client() {}
public static void main(String[] args) {
try {
// Getting the registry
Registry registry = LocateRegistry.getRegistry(null);
// Looking up the registry for the remote object
Hello stub = (Hello) registry.lookup("Hello");
// Calling the remote method using the obtained object
stub.printMsg();
// System.out.println("Remote method invoked");
} catch (Exception e) {
System.err.println("Client exception: " + e.toString());
e.printStackTrace();
}
}
}
Output:
Experiment - 6

Aim: Simulate Balanced Sliding Window Protocol in 'C'.

Introduction: Sliding window protocols are data link layer protocols for reliable and
sequential delivery of data frames. The sliding window is also used in Transmission Control
Protocol. In this protocol, multiple frames can be sent by a sender at a time before
receiving an acknowledgment from the receiver. The term sliding window refers to the
imaginary boxes to hold frames. Sliding window method is also known as windowing.

Theory:

Working Principle: In these protocols, the sender has a buffer called the sending window and
the receiver has buffer called the receiving window.

The size of the sending window determines the sequence number of the outbound frames. If
the sequence number of the frames is an n-bit field, then the range of sequence numbers that
can be assigned is 0 to 2𝑛−1. Consequently, the size of the sending window is 2𝑛−1. Thus in
order to accommodate a sending window size of 2𝑛−1, a n-bit sequence number is chosen.

The sequence numbers are numbered as modulo-n. For example, if the sending window size is
4, then the sequence numbers will be 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, and so on. The number of bits
in the sequence number is 2 to generate the binary sequence 00, 01, 10, 11.

The size of the receiving window is the maximum number of frames that the receiver can accept
at a time. It determines the maximum number of frames that the sender can send before
receiving acknowledgment.

Example: Two processes p and q, each sending an infinite array of words to the other.
For Process p:
• inp: An infinite array of words to be sent to process q
• outp:An infinite array of words being received from process q
• Initially for all i, out outp[i] = udef
• Sp: The lowest numbered word that p still expects to receive from q. At any time, p has
already written out outp[0] through out outp[i].

Source Code:

#include <stdio.h>
int main() {
int w, i, f, frames[50];
printf("Enter window size: ");
scanf("%d", &w);
printf("\nEnter number of frames to transmit: ");
scanf("%d", &f);
printf("\nEnter %d frames: ", f);
for (i = 1; i <= f; i++) {
scanf("%d", &frames[i]);
}
printf("\n\nSliding window protocol\n\n");
printf("After sending %d frames at each stage sender waits for acknowledgement sent by
the receiver\n\n", w);
for (i = 1; i <= f; i++) {
if (i % w == 0) {
printf("%d\n", frames[i]);
printf("Acknowledgement of above frames sent is received by sender\n\n");
} else
printf("%d ", frames[i]);
}
if (f % w != 0)
printf("\nAcknowledgement of above frames sent is received by sender\n");
return 0;
}

Output:
Experiment - 7

Aim: Implement CORBA mechanism by using 'C++' program at one end and 'Java program
on the other.

Introduction: CORBA, or the Common Object Request Broker Architecture, is a


middleware that enables seamless communication between distributed objects written in
different programming languages. It provides a framework for building distributed systems
where objects can transparently interact with each other, irrespective of the programming
language in which they are implemented. This architecture uses a language-neutral interface
definition language called IDL (Interface Definition Language) to define the interfaces of
distributed objects. CORBA implementations typically involve the use of an Object Request
Broker (ORB) to handle communication and invocation of methods across distributed
objects. This enables developers to create modular and interoperable applications by allowing
objects written in C++ to communicate with objects implemented in Java, as demonstrated in
the provided example.

Theory: CORBA, the Common Object Request Broker Architecture, is a powerful tool
for distributed programming. CORBA is a mechanism in software for normalizing the
method-call semantics between application objects that reside either in the same address
space (application) or remote address space (same host, or remote host on a network).
Version 1.0 was released in October 1991. CORBA uses an interface definition language
(IDL) to specify the interfaces that objects will present to the outside world. CORBA
then specifies a mapping from IDL to a specific implementation language like C++or
Java. Standard mappings exist for Ada, C ,C++, Lisp, Ruby, Smalltalk, Java, COBOL,
PL/Iand Python. There are also nonstandard mappings for Perl, Visual Basic, Erlang, and Tcl
implemented by object request brokers(ORBs) written for those languages. The CORBA
specification dictates that there shall be an ORB through which the Application
interacts with other objects. In practice, the application simply initializes the ORB, and
accesses an internal Object Adapter which maintains such issues as reference counting,
object (and reference) instantiation policies, object lifetime policies, etc. The Object Adapter
is used to register instances of the generated code classes. Generated code classes are the
result of compiling the user IDL code, which translates the high-level interface definition into
an OS-and language-specific class base for use by the user application. This step is necessary
in order to enforce the CORBA semantics and provide a clean user process for interfacing
with the CORBA infrastructure.

Description: Data communication from client to server is accomplished through a well


defined object-oriented interface. The object request broker (ORB) determines the location of
the target object, sends a request to that object, and returns any response back to the caller.

Source Code:

// Creating the Server


#include <iostream>
#include "OB/CORBA.h"
#include <OB/Cosnaming.h>
#include "crypt.h"
#include "cryptimpl.h"
using namespace std;
int main (int argc, char **argv){
CORBA::ORB_var orb;
CryptographicImpl *CrypImpl = NULL;
try{
orb = CORBA::ORB_init (argc, argv);
CORBA::Object_var rootPOAObj =
orb->resolve_initial_references ("RootPOA");
PortableServer::POA_var rootPOA =
PortableServer::POA::_narrow (rootPOAObj.in ());
CORBA::PolicyList policies;
policies.length (1);
policies[0] =
rootPOA->create_thread_policy (PortableServer::SINGLE_THREAD_MODEL);
PortableServer::POAManager_var manager = rootPOA->the_POAManager ();
PortableServer::POA_var myPOA =
rootPOA->create_POA ("myPOA", manager, policies);
CORBA::ULong len = policies.length ();
for (CORBA::ULong i = 0; i < len; i++)
policies[i]->destroy ();
CORBA::Object_var rootContextObj =
orb->resolve_initial_references ("NameService");
CosNaming::NamingContext_var nc =
CosNaming::NamingContext::_narrow (rootContextObj.in ());
CrypImpl = new CryptographicImpl (orb);
PortableServer::ObjectId_var myObjID = myPOA->activate_object (CrypImpl);
CORBA::Object_var o = myPOA->servant_to_reference (CrypImpl);
converted to a character string
CORBA::String_var s = orb->object_to_string (o);
cout << "The IOR of the object is: " << s.in () << endl;
CosNaming::Name name;
name.length (1);
name[0].id = (const char *) "CryptographicService";
name[0].kind = (const char *) "";
nc->rebind (name, o);
manager->activate ();
cout << "The server is ready.
Awaiting
for incoming requests..." << endl;
orb->run ();
} catch (const CORBA::Exception & e)
{
cerr << e << endl;
}
if (CrypImpl)
CrypImpl->_remove_ref ();
if (!CORBA::is_nil (orb)){
try{
orb->destroy ();
cout << "Ending CORBA..." << endl;
}
catch (const CORBA::Exception & e){
cout << "orb->destroy() failed:" << e << endl;
return 1;
}
}
return 0;
}

PortableServer::ObjectId_var myObjID = myPOA->activate_object (CrypImpl);


CORBA::Object_var o = myPOA->servant_to_reference (CrypImpl);
CORBA::String_var
s = orb->object_to_string (o);
cout << "The IOR of the object is: " << s.in () << endl;
CosNaming::Name name;
name.length (1);
name[0].id = (const char *) "CryptographicService";
name[0].kind = (const char *) "";
nc->rebind (name, o);
manager->activate ();
cout << "The server is ready.
Awaiting
for incoming requests..." << endl;
orb->run ();
}

catch (const CORBA::Exception & e)


{
cerr << e << endl;
}

if (CrypImpl)
CrypImpl->_remove_ref ();
if (!CORBA::is_nil (orb)){
try{
orb->destroy ();
cout << "Ending CORBA..." << endl;
}
catch (const CORBA::Exception & e){
cout << "orb->destroy() failed:" << e << endl;
return 1;
}
}
return 0;
}

cout << "Enter encryption key: ";


cin >> key;
}
while (cin.fail ());
do{
if (cin.fail ()){
cin.clear ();
cin >> dummy;
}
cout << "Enter a shift: ";
cin >> shift;
}
while (cin.fail ());
getline (cin, dummy);
cout << "Enter a plain text to encrypt: ";
getline (cin, info_in);
inseq = manager->encrypt (info_in.c_str (), key, shift);
cout << "------------------------------------------" << endl;
cout << "Encrypted text is: " << inseq->get_buffer () << endl;
info_out = manager->decrypt (inseq.in (), key, shift);
cout << "Decrypted text is: " << info_out.in () << endl;
cout << "-------------------------------------------" << endl;
cout << "Exit? (y/n): ";
cin >> exit;
}

while (exit != "y");


manager->shutdown ();
}

catch (const std::exception & std_e){


cerr << std_e.what () << endl;
}
} catch (const CORBA::Exception & e){
cerr << e << endl;
}

if (!CORBA::is_nil (orb)){
try{
orb->destroy ();
cout << "Ending CORBA..." << endl;
}
catch (const CORBA::Exception & e){
cout << "orb->destroy failed:" << e << endl;
return 1;
}
}
return 0;
}
Output:

Enter encryption key: my_secret_key


Enter a shift: 3
Enter a plain text to encrypt: Hello, CORBA!
------------------------------------------
Encrypted text is: Khoor, FRUED!
Decrypted text is: Hello, CORBA!
-------------------------------------------
Exit? (y/n): n
Enter encryption key: another_key
Enter a shift: 5
Enter a plain text to encrypt: Freecodez
------------------------------------------
Encrypted text is: TujnFJ LUX-3
Decrypted text is: Freecodez
-------------------------------------------
Exit? (y/n): y
Experiment - 8

Aim: Develop a client server application which implements File Transfer protocol.

Introduction: The client accepts filename through the keyboard and sends it to the server. The
server reads the file and transfers the content back to the client.

Theory:
Algorithm: server side
Begin
Create an object of server socket class and listen for incoming client connection in a
specified port.
When a client connection is established, create input and output streams for this connection.
While (true)
a. Read a file name from the input stream.
b. Read the content of the file requested by the client.
c. Send the file content to the client.
d. Close server and client socket.
End

Algorithm: client side


Begin
Establish a connection to the server program. Use IP address and port number of the server.
Crete input and output streams for the established connection.
Read filename from the keyboard and send to the server.
Display contents of file sent to the server.
Close the connection.
End

Source Code:

// FTP Server
import java.io.*;
import java.net.*;

public class FTP_Server {


ServerSocket server; // create a server.....
Socket con = null; // to establish a connection
ObjectOutputStream out;
ObjectInputStream in ;
String filename = "";
String contents = "";
File file = null;
void start() throws UnknownHostException, IOException, FileNotFoundException {
try {
server = new ServerSocket(2004, 10); // port,max Queue.....
System.out.println("Server - listening on port " + 2004);
System.out.println("Server - Waiting for the Client.....");
con = server.accept();
System.out.println("Server - Connection received from " +
con.getInetAddress().getHostName());
out = new ObjectOutputStream(con.getOutputStream());
in = new ObjectInputStream(con.getInputStream());
serverMessage("Server - Connection to Client Failed.....");
do {
try {
filename = (String) in.readObject();
System.out.println("Server > Got filename From Client -> " + filename);
File file = new File(filename);
FileInputStream fin = new FileInputStream(file);
DataInputStream din = new DataInputStream(fin);
while ((contents = din.readLine()) != null) {
System.out.println("Inside" + contents);
serverMessage(contents); //sending file contents.....
}
if (filename.equals("bye"))
serverMessage("bye");
} catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
}
} while (!filename.equals("bye"));
} catch (IOException e) {} finally {
try {
in.close();
out.close();
server.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
void serverMessage(String str) throws IOException {
try {
out.writeObject(str); // WRITING TO SERVER'S OUTPUT BUFFER.....
out.flush(); // clearing the output buffer.....
System.out.println("Server -writing Message to Server's output buffer....." + str);
} catch (IOException ioe) {}
}

public static void main(String[] args) throws UnknownHostException, IOException,


NullPointerException {
FTP_Server server = new FTP_Server();
while (true) {
try {
server.start();
} catch (NullPointerException e) {}
}
}
}
// FTP Client
import java.io.*;
import java.net.*;

public class FTP_Client {


Socket client = null; // create a client.....
String file = "test.txt";
ObjectOutputStream out;
ObjectInputStream in ;
String msg;

void start() throws UnknownHostException, IOException {


System.out.println("Filename : " + file);
try {
client = new Socket("localhost", 2004); //inetaddress ip ,port
System.out.println("Client > Connecting to server.....");
out = new ObjectOutputStream(client.getOutputStream());
in = new ObjectInputStream(client.getInputStream());
ClientMessage("Client > Connection to server Failed.....");

do {
try {
msg = (String) in.readObject();
System.out.println("Client > Message From Server ->" + msg);
ClientMessage(file);
} catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
}
} while (!msg.equals("bye"));
} catch (IOException e) {}
}
void ClientMessage(String str) throws IOException {
try {
System.out.println("Client > Writing to Client's output buffer....." + str);
out.writeObject(str); // WRITING TO CLIENT'S OUTPUT BUFFER.....
out.flush(); // clearing the output buffer.....

} catch (IOException ioe) {}


}
public static void main(String[] args) throws UnknownHostException, IOException {
FTP_Client client = new FTP_Client();
client.start();
}
}
Output:

Server side
Server – listening on port 2004
Server – Waiting for the Client…..
Server > Got filename from Client -> test.txt

Client Side
Filename : test.txt
Client > Connecting to server…..
Client > message from server -> Hello World.
Experiment - 9

Aim: Implement a client server application which implements Name Server.

Introduction: In distributed systems, a Name Server plays a crucial role in providing a


centralized directory service for mapping human-readable names to network addresses. This
facilitates the location of various resources or services in the network. The client-server
application presented here demonstrates a simple Name Server system using Java. Clients can
register names along with corresponding addresses, and other clients can then query the Name
Server to obtain the address associated with a given name.

Theory: The Name Server is implemented using Java's socket programming. The server listens
for client requests and maintains a mapping of names to addresses. Clients can register their
names and addresses with the server, and other clients can query the server to obtain the address
associated with a particular name.

Source Code:

// Server
import java.io.*;
import java.net.*;
import java.util.HashMap;
import java.util.Map;

public class NameServer {


private static final int PORT = 9999;
private static Map<String, String> nameToAddressMap = new HashMap<>();

public static void main(String[] args) {


try {
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println("Name Server is running on port " + PORT);
while (true) {
Socket clientSocket = serverSocket.accept();
new ServerThread(clientSocket).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}

private static class ServerThread extends Thread {


private Socket clientSocket;
private BufferedReader reader;
private PrintWriter writer;

public ServerThread(Socket clientSocket) {


this.clientSocket = clientSocket;
try {
reader = new BufferedReader(new
InputStreamReader(clientSocket.getInputStream()));
writer = new PrintWriter(clientSocket.getOutputStream(), true);
} catch (IOException e) {
e.printStackTrace();
}
}

@Override
public void run() {
try {
String request = reader.readLine();
processRequest(request);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

private void processRequest(String request) {


String[] parts = request.split(":");
if (parts.length == 2 && parts[0].equals("REGISTER")) {
String name = parts[1];
String address = clientSocket.getInetAddress().getHostAddress();
registerName(name, address);
} else if (parts.length == 1 && parts[0].equals("QUERY")) {
String name = reader.readLine();
queryAddress(name);
}
}
private void registerName(String name, String address) {
nameToAddressMap.put(name, address);
System.out.println("Registered: " + name + " -> " + address);
}

private void queryAddress(String name) {


String address = nameToAddressMap.get(name);
if (address != null) {
writer.println("Address: " + address);
} else {
writer.println("Name not found");
}
}
}
}
// Client
import java.io.*;
import java.net.*;
public class NameClient {
private static final int PORT = 9999;
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost", PORT);
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
System.out.println("Choose an option:\n1. Register a name\n2. Query an address");
int option = Integer.parseInt(reader.readLine());
if (option == 1) {
System.out.print("Enter name to register: ");
String name = reader.readLine();
writer.println("REGISTER:" + name);
} else if (option == 2) {
System.out.print("Enter name to query: ");
String name = reader.readLine();
writer.println("QUERY");
writer.println(name);
String response = new BufferedReader(new
InputStreamReader(socket.getInputStream())).readLine();
System.out.println(response);
} else {
System.out.println("Invalid option");
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

Output:
v Client Side

v Server Side

You might also like