Vous êtes sur la page 1sur 23

DISTRIBUTED SYSTEMS LAB PROGRAMS GENERAL INSTRUCTIONS: 1. YOU SHOULD USE PUNCHED FILE FOR DISTRIBUTED LAB MANUAL.

2. FRONT PAGE OF THE FILE AND THE INDEX PAGE SHOULD BE PRINT OUT 3. INDEX SHOULD CONTAIN (SR. NO. , NAME OF THE PRACTICAL, DATE , GRADE AND SIGN) 4. YOU WILL USE PRACTICAL SHEET i.e. ONE SIDE PLAIN AND ONE SIDE RULED 5. THEORY WILL BE WRITTERN ON THE LEFT SIDE OF THE PAGE WITH PENCIL 6. CODE OF THE PROGRAM WILL BE WRITTERN ON RIGHT SIDE WITH PEN. PROGRAM NO. 1 Simulate the functioning of Lamports Logical clock in C. Theory: Lamport proposed a scheme to order the events in a distributed system by using logical clocks. Due to the absence of synchronized clock and global time in a distributed system, the order in which events occur at two different machine is impossible to be determined based on the local time at which they occurred. Algorithm: This simulation takes place by using the following concepts. 1) Happened Before Relationship 2) Logical clocks For any two events a & b, a is said to happened before b is denoted as a b, if they are in same process. If events occur at different processes then for any message (m) Send (m) Receive (m)

If a b and b c then a c i.e. is transitive. If events casually affects each other then they are said to be casually related events a b Two events are concurrent if a b and b a i.e. a||b Conditions satisfied by Logical Clocks. a) For any two events occurring on same process, a b if Ci[a] < Ci[b]. b) Clock Ci is implemented between any two events of the same process as Ci = Ci + d (d>0) c) If event a is sending message by process Pi and is received by process Pj, then tm = Ci(a) Cj = max(Cj+d, tm), d>0 CODE: #include<stdio.h> #include<conio.h> void main() { int p1[10],p2[10]; int e,i,m1,m2; printf("enter the no of events in p1 & p2"); scanf("%d",&e); printf("enter the event of p1 which will send msg"); scanf("%d",&m1); printf("enter the event of p2 which will recieve the msg"); scanf("%d",&m2); p[1]=1; p[2]=1; for(i=2;i<=e;i++) { if(i!=m2) {

p1[i]=p1[i-1]+1; p2[i]=p2[i-1]+1; } else p2[i]=p1[m1]+1; } printf("event of p1 are"); for(i=1;i<=e;i++) { printf("%d",p1[i]); } printf("event of p2 are"); for(i=1;i<=e;i++) { printf("%d",p2[i]); } } PROGRAM NO. 2 Simulate the Distributed Mutual Exclusion in C. THEORY: |

If a collection of processes share a resource or collectionof resources, then often mutual exclusion is required to revent interferences and ensure consistency when accessing the resources. This is critical section problem, familiar in the domain of operating systems. In a distributed system, however, neither sahred variables nor facilites supplied by a single local kernel can be used to solve it, in general. We require a solution to distributed mutual exclusion: one that is based solely on message passing. Algorithm: On initiation

state:= RELEASED; To enter the section state:= WANTED; Multicast request to all processes; T:= request's timestamp; Wait until (number of replies receeived = (N-1)); state:= HELD; On receipt of a request <T CODE: #include<stdio.h> #include<conio.h> #include<string.h> #include<pthread.h> #include<semaphore.h> #include<unistd.h> void *thread_func(void *arg); thread_mutex_t_work_mutex; #define work_size 1024 char work_area(work_size); int time_to_exit(); int main() { int res; pthread=t; a=thread; void *thread_result; res=pthread_mutex_unit(&work_mutex,null); if(res!=0) { perror("mutex initialization failed"); exit(exit_failure); } res=pthread_create(&a_thread,null,thread function,null); if(res!=0) {

perror("thread creation failure"); exit(exit_failure); } pthrad_mutex_lock(&work_mutex); printf("input some text,end to finish \n"); while(!time_to_exit) { fgets(work_area,work_size,stdin); pthread_mutex_unlock(&work_mutex); while(1) } { pthread_mutex-lock(&work_mutex); if(work_area[0]!='\0') { pthread_mutex_unlock(&work_mutex); sleep(1); } else { break; } } pthread_mutex_unlock(&work_mutex); printf("\n waiting for thread to finish..."); res=pthread_join(a_thread.thread_result); if(res!=0) { perror("thread join failed"); exit(exit failure); } printf("thread joined"); pthread_mutex_destroy(&work_mutex); exit(exit success); } void *thread_function(void *arg)

{ sleep(1); pthread_mutex_lock(&work_mutex); while stramp("end",work_aarea,39!=0) { printf("you input %d char \n",strlen(work_area,-1); work_area[0]='\0'; pthread_mutex_unlock(&work_mutex); sleep(1); thread_mutex_lock(&work_mutex); } while(work-area[0]=='\0') { pthread_mutex_unlock(&work_mutex); sleep(1); pthread_mutex_lock(&work_mutex); } } PROGRAM NO. 3 Implement a distributed Chat server using TCP sockets . The chat system consists of two distributed components: chat server and chat client, which may run on different hosts in the network. We provide you the server side of the system. We also provide a skeleton of the chat client that includes a simple user interface to allow users of the chat client to type in control commands and chat messages. You must add client support for all communication, including requesting chat server location information from a location server, the exchange of control messages with the server, and the display of received chat messages. Finally, your chat client must detect chat server failures and attempt a simple form of recovery. The chat server conducts a chat session in chat rooms. At any given time there may be multiple chat clients in a chat session. The chat server is responsible for managing all the chat clients in the session and distributing chat messages. A chat client starts by

requesting the communication parameters (server name and port numbers) for the chat server from a location server. CODE: TCP echo client #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/stat.h> #include <netinet/in.h> #include <arpa/inet.h> #include <fcntl.h> #include <time.h> #include <unistd.h> #include <sys/signal.h> #include <string.h> #define SERV_TCP_PORT 9000 #define SERV_HOST_ADDR "127.0.0.1" int main() { int sockfd = 0; int i = 0; int count = 0; int choice = 0; char string[20]; char data[20]; struct sockaddr_in sa; /* socket setup */ bzero((char*)&sa,16); sa.sin_family = AF_INET; sa.sin_addr.s_addr = inet_addr(SERV_HOST_ADDR); sa.sin_port = htons(SERV_TCP_PORT); if((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { printf("\n socket error \n "); goto end; }

if(connect(sockfd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { printf("\n connect error \n"); goto end; } /* socket setup */ printf("\n\n"); printf("............................... TCP ECHO CLIENT .................................\n"); start: printf("\n enter string: \t"); scanf("%s", &string); strcpy(data, string); /* socket usage */ write(sockfd, &data, sizeof(data)); bzero((char*) &data, sizeof(data)); read(sockfd, &data, sizeof(data)); if(strcmp(data, string) == 0) printf("\nServer Response: %s\n", data); else printf("\nError in Response\n"); printf("............................... TCP ECHO CLIENT ................................\n"); end: close(sockfd); return 0; } /* * TCP echo server */ #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/stat.h> #include <netinet/in.h> #include <arpa/inet.h> #include <fcntl.h> #include <time.h> #include <unistd.h> #include <sys/signal.h> #include <string.h>

#define SERV_TCP_PORT 9000 #define SERV_HOST_ADDR "127.0.0.1" char data[20]; int main() { int sockfd = 0; int newsockfd = 0; int childpid = 0; int clilen = 0; struct sockaddr_in cli_addr,serv_addr; if((sockfd = socket(AF_INET,SOCK_STREAM,0))<0) { printf("server cant open stream socket!\n"); exit(0); } bzero((char *)&serv_addr,sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(SERV_TCP_PORT); if(bind(sockfd, (struct sockaddr *) &serv_addr ,sizeof(serv_addr)) < 0) { printf("\n bind error \n"); exit(0); } listen(sockfd,5); printf("\n\n"); printf("............................... TCP ECHO SERVER ................................\n"); for(;;) { clilen = sizeof(serv_addr); if((newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen)) <0) { printf("SERVER ACCEPT ERROR !"); exit(0); } if((childpid = fork()) < 0){ printf("\nSERVER FORK ERROR !");

exit(0); } else if(childpid == 0) { close(sockfd); read(newsockfd, &data, sizeof(data)); write(newsockfd, &data, sizeof(data)); printf("client string : %s\n", data); } printf("\n\n"); printf("............................... TCP ECHO SERVER ................................\n"); close(newsockfd); exit(0); } } PROGRAM NO. 4 Implement RPC mechanism for a file transfer acoss a network in C THEORY: Remote Procedure Call (RPC) is an inter-process communication that allows a computer program to cause asubroutine or procedure to execute in another address space (commonly on another computer on a shared network) without the programmer explicitly coding the details for this remote interaction. That is, the programmer writes essentially the same code whether the subroutine is local to the executing program, or remote. Message passing: An RPC is initiated by the client, which sends a request message to a known remote server to execute a specified procedure with supplied parameters. The remote server sends a response to the client, and the application continues its process. There are many variations and subtleties in various implementations, resulting in a variety of different (incompatible) RPC protocols. While the server

is processing the call, the client is blocked (it waits until the server has finished processing before resuming execution). An important difference between remote procedure calls and local calls is that remote calls can fail because of unpredictable network problems. Also, callers generally must deal with such failures without knowing whether the remote procedure was actually invoked.Idempotent procedures (those that have no additional effects if called more than once) are easily handled, but enough difficulties remain that code to call remote procedures is often confined to carefully written low-level subsystems. Sequence of events during a RPC: The client calls the Client stub. The call is a local procedure call, with parameters pushed on to the stack in the normal way. 2. The client stub packs the parameters into a message and makes a system call to send the message. Packing the parameters is called marshalling. 3. The kernel sends the message from the client machine to the server machine. 4. The kernel passes the incoming packets to the server stub. 5. Finally, the server stub calls the server procedure. The reply traces the same steps in the reverse direction.
1.

CODE: /* THE CLIENT SIDE */ #include<stdio.h> #include<conio.h> #include<rpc/rpc.h> #include<rpc svc/rusers.h> /* a pgm that calls the ruserprog *rpc program */ main(int argc,char **args) { unsigned long nusers; enum int=start cs;

if(arfs!=2) { fprint(stderr,"usage:rusers hostname \n"); exit(1); } if(cs=rpc_call(argu[1],ruserprog,ruservers,pusersproc_num,xdr_void, (char*)0,xdr_u_long,(char*)&nusers,"visible")!=rpc_success) { clnt_perrno(cs); exit(1); } fprint(stderr,"%d users on %s \n",nusres,argu[1]); exit(0); }

/* THE SERVER SIDE */ #include<stdio.h> #include<conio.h> #include<rpc/rpc.h> #include<rpc svc/rusers.h> void *rusers(); main() { if(rpc_reg(rusersprog,rusersvers,rusersproc_num,reusers,xdr_void,xdr_u_lon 1) { fprintf(stderr,"couldn't register \n"); exit(1); } svc_run(); fprintf(stderr,"error:svc_run returned \n"); exit(1); } /*CLIENT SIDE */

#include<stdio.h> #include<string.h> #include<rpc/rpc.h> #include<rls.h> main(arg c,arg v) int argc;char *argv[]; { char dir[dir_size]; /* call the remote procedure if registered */ strcpy(dir,argv[2]); read_dir(argv[1],dir); /* sprew out the results & ball out of here !*/ printf("%s \n",dir); exit(0); }read_dir(host,dir) char *dir,*host; { extern boot_t xdr_dir(); enum clnt_stat; clnt_stat=call rpc(host,dirpog,dirvers,readdir,xdr_dir,dir,xdr_dir,dir); if(clnt_stat!=0) clnt_perrno(clnt_stat) } PROGRAM NO. 5 Implement Java RMI mechanism for accessing methods of remote system. Theory: RMI applications are often comprised of two separate programs : a server and client to invoke the events and some of object make reference to them accessible and wait for client to invoke methods on these objects. A typical application gets remote reference to one or more remote objects in the server and the client and pass information back and forth.

Distributed Remote Objects 1. Locate remote objects 2. Communicate with remote object RMI = RPC + Object Orientation

CLIENT
Request message

SERVER
Get request Select object Execute Method Send reply

do operation . . (wait) . (continue)

Reply Message

Request Reply Communication for RMI

Client
Object A Object B

Request

Server
Skeleton of B Remote Objects B Remote Reference Module

Reply Remote Reference Module


Communication Module

Role of proxy skeleton in RMI

Skeleton & Dispatcher for Bs Class

Request Object A Proxy for B Reply Remote Object for B

Remote Reference Module

Comm. Module

Comm. Module

Remote Reference Module

Role of Proxy & Skeleton in RMI CODE: import java.io.*; import java.net.*; class client1 { public static void main(String args[]) throws IOException,UnknownHostException { String message; String return_message; BufferedReader inFromUser =

new BufferedReader(new InputStreamReader(System.in)); Socket clientSocket = new Socket("localhost", 6789); DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream()); BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); message = inFromUser.readLine(); outToServer.writeBytes(message + '\n'); return_message = inFromServer.readLine(); System.out.println("FROM SERVER: " + return_message); clientSocket.close(); } }

import java.io.*; import java.net.*; class client2 { public static void main(String args[]) throws IOException,UnknownHostException { String message;

String return_message; BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in)); Socket clientSocket = new Socket("localhost", 6790); DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream()); BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); message = inFromUser.readLine(); outToServer.writeBytes(message + '\n'); return_message = inFromServer.readLine(); System.out.println("FROM SERVER: " + return_message); clientSocket.close(); } }

import java.io.*; import java.net.*; class server {

public static void main(String argv[]) throws IOException,UnknownHostException { String client_msg1,client_msg2; String msg_client1,msg_client2; ServerSocket welcomeSocket1 = new ServerSocket(6789); ServerSocket welcomeSocket2 = new ServerSocket(6790); while(true) { Socket connectionSocket1 = welcomeSocket1.accept(); //For client1; BufferedReader inFromClient1 = new BufferedReader(new InputStreamReader(connectionSocket1.getInputStream())) ; DataOutputStream outToClient1 = new DataOutputStream(connectionSocket1.getOutputStream()); //for client2; Socket connectionSocket2 = welcomeSocket2.accept(); BufferedReader inFromClient2 = new BufferedReader(new InputStreamReader(connectionSocket2.getInputStream())) ; DataOutputStream outToClient2 = new DataOutputStream(connectionSocket2.getOutputStream());

client_msg1 = inFromClient1.readLine(); msg_client2 = client_msg1+ '\n'; outToClient2.writeBytes(msg_client2); client_msg2=inFromClient2.readLine(); msg_client1=client_msg2+'\n'; outToClient1.writeBytes(msg_client1); } } } PROGRAM NO. 6 Implement CORBA mechanism THEORY:CORBA The Common Object Request Broker Architecture (or CORBA) is an industry standard developed by the Object Management Group (OMG) to aid in distributed objects programming. It is important to note that CORBA is simply a specification. A CORBA implementation is known as an ORB (or Object Request Broker). There are several CORBA implementations available on the market such as VisiBroker, ORBIX, and others. JavaIDL is another implementation that comes as a core package with the JDK1.3 or above. CORBA was designed to be platform and language independent. Therefore, CORBA objects can run on any platform, located anywhere on the network, and can be written in any language that has Interface Definition Language (IDL) mappings. Similar to RMI, CORBA objects are specified with interfaces. Interfaces in CORBA, however, are specified in IDL. While IDL is similar to C++, it is important to note that IDL is not a programming language. The Genesis of a CORBA Application There are a number of steps involved in developing CORBA applications. These are:

1. Define an interface in IDL 2. Map the IDL interface to Java (done automatically) 3. Implement the interface 4. Develop the server 5. Develop a client 6. Run the naming service, the server, and the client. We now explain each step by walking you through the development of a CORBA-based file transfer application, which is similar to the RMI application we developed earlier in this article. Here we will be using the JavaIDL, which is a core package of JDK1.3+. CODE: import java.io.*; public class FileServant extends _FileInterfaceImplBase { public byte[] downloadFile(String fileName){ File file = new File(fileName); byte buffer[] = new byte[(int)file.length()]; try { BufferedInputStream input = new BufferedInputStream(new FileInputStream(fileName)); input.read(buffer,0,buffer.length); input.close(); } catch(Exception e) { System.out.println("FileServant Error: "+e.getMessage()); e.printStackTrace(); } return(buffer); } } Develop the server

The next step is developing the CORBA server. The FileServer class, shown in Code Sample 7, implements a CORBA server that does the following: 1. Initializes the ORB 2. Creates a FileServant object 3. Registers the object in the CORBA Naming Service (COS Naming) 4. Prints a status message 5. Waits for incoming client requests FileServer.java import java.io.*; import org.omg.CosNaming.*; import org.omg.CosNaming.NamingContextPackage.*; import org.omg.CORBA.*; public class FileServer { public static void main(String args[]) { try{ // create and initialize the ORB ORB orb = ORB.init(args, null); // create the servant and register it with the ORB FileServant fileRef = new FileServant(); orb.connect(fileRef); // get the root naming context org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService"); NamingContext ncRef = NamingContextHelper.narrow(objRef); // Bind the object reference in naming NameComponent nc = new NameComponent("FileTransfer", " "); NameComponent path[] = {nc}; ncRef.rebind(path, fileRef);

System.out.println("Server started...."); // Wait for invocations from clients java.lang.Object sync = new java.lang.Object(); synchronized(sync){ sync.wait(); } } catch(Exception e) { System.err.println("ERROR: " + e.getMessage()); e.printStackTrace(System.out); } } } Develop a client The next step is to develop a client. An implementation is shown in Code Sample 8. Once a reference to the naming service has been obtained, it can be used to access the naming service and find other services (for example the FileTransfer service). When the FileTransfer service is found, the downloadFile method is invoked. FileClient.java import java.io.*; import java.util.*; import org.omg.CosNaming.*; import org.omg.CORBA.*; public class FileClient { public static void main(String argv[]) { try { // create and initialize the ORB ORB orb = ORB.init(argv, null); // get the root naming context org.omg.CORBA.Object objRef =

orb.resolve_initial_references("NameService"); NamingContext ncRef = NamingContextHelper.narrow(objRef); NameComponent nc = new NameComponent("FileTransfer", " "); // Resolve the object reference in naming NameComponent path[] = {nc}; FileInterfaceOperations fileRef = FileInterfaceHelper.narrow(ncRef.resolve(path)); if(argv.length < 1) { System.out.println("Usage: java FileClient filename"); } // save the file File file = new File(argv[0]); byte data[] = fileRef.downloadFile(argv[0]); BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(argv[0])); output.write(data, 0, data.length); output.flush(); output.close(); } catch(Exception e) { System.out.println("FileClient Error: " + e.getMessage()); e.printStackTrace(); } } }