Document Sample
exercise Powered By Docstoc
					LABORATOIRE DE TÉLÉINFORMATIQUE                            Communication Software Engineering

A simple user driven FTP Client

In this exercise, we propose to create a program that accesses an FTP server. In order to keep it at a
reasonable level of difficulties, we will rely on some interventions of the operator to retrieve the data.
However, this program forms a very good basis to create tools that are capable of retrieving
automatically data from FTP sites, for example, or to build an FTP server on a particular machine.

This exercise will also help the participant to understand the use of TCP/IP or the functioning of other
protocols similar to FTP. It will show how concurrency or multi-threading, used in the right manner,
actually clarifies the structures of programs, makes them easily extensible, and simplifies their testing.

Here is the structure of the FTP protocol.

                      FTP             Command channel             FTP server
                                        Data channel

This protocol uses two TCP channels. The command channel is established when the user logs
her/himself into the FTP server, and it remains active until the user logs out. The data channel is set up
before each data transfer, and closed after each transfer to mark the end of the data transfer. The
commands sent to the server and the responses received from it are written in clear ASCII text, and
can thus be typed and displayed on a terminal. The command channel is opened on TCP port 21,
reserved for this purpose.

The login is done by sending the following commands into the command channel (all FTP-servers
await these commands on the command channel):
     USER usernameCR
       response from the server
     PASS passwdCR
        response from the server
        returns the list of commands known by the server, directly on the command channel

Data storage/retrieval is done in several steps. The client must first open a local TCP socket in passive
mode (TCPDaemonSocket), and then send the command that requests the server to establish a channel
from its own port to the local port just opened. Here is that command (notice that command PORT
needs commas, not dots):
    PORT 128,178,xxx,yyy,19,136 CR
The first 4 numbers are the parts of the IP number of the client machine. The two last numbers give
the local port number that has been selected (e.g., 19*256 + 136 == 5000). If the client is located on
the machine with IP number 128,178,xxx,yyy, and has instantiated a daemon with port number 5000,
the port command indicated above establishes a connection between the FTP server and that client.
The opening of the new connection by the server is detected by the client (SocketCreated()), which

gets then a new data channel. Data are produced by the server and sent into the channel, for example
when it receives the following order:
This command requests the server to send the list of the filenames contained in the current directory
into the data channel just opened. The client can just read the data coming out of this channel, and
display them on the terminal. After the last character of the list has been sent, the data channel is
closed. This event unblocks the last TCP->Recv() call, which was waiting for the subsequent data, but
it brings zero character back. It is the way the client knows that the data transfer is finished. The
PORT command must be replayed each time the list of file names is to be sent through the data

The next command
    RETR filenameCR
requests the server to read the file filename, and to send its content into the data channel opened by the
PORT command. It is up to the client to read its content from its side of the channel, and store it on the
disk or wherever it wants them to be placed. The storage of data uses the data channel in the same
way, simply with data flowing in the opposite direction. The storage command is named
STOR filename.


The program that we propose to create is described below. You must write it from scratch in a file
named ftpTest.scxx, but you can look at and
click on accès à la liste des squelettes on that page to get help. To compile it, type make ftpTest in the
directory containing ftpTest.scxx.

1. Instantiate the two Xterm
2. Instantiate the socket of the command channel (indicate the name of some server and port 21).
3. Instantiate a TCP daemon, with port = 5000 (for the data channel).
4. Loop on the simultaneous waiting of the following events in the main (the letters refer to the ones
   on the figure below) :
       a) Read from XTerm1. When data are typed in, send them to the command channel.
            Note: the Xterm::ReadString gets its data into a CharString, whereas the TCPSocket::Send
            needs a char[xx]. The following command casts a CharString into a char[xx] :
            (const char*) chrStr.
       b) Receive data from TCP command channel. When data arrive, display them on XTerm1.
            Note that you must add a zero at the end of the buffer to mark the end of the string, before
            calling the display command.
       c) Await a data channel creation (SocketCreated(), triggered each time the server establishes
            a new connection), and when this happens, display a message in XTerm1 and remember
            that it is open.
       d) When a data channel is open, await data from the channel just created and when data
            arrive, display them on XTerm2.
       e) If the data channel accepts the receive method (TCP->Recv()) with zero data, meaning
            that it has been closed by the server, delete the channel socket (delete soc;) in order to
            close it from the client side, and reset the flag indicating that the channel is open.
5. Load the program described in the first four points, which automatically establishes the TCP
   connection with the server.
6. Type in the commands indicated above (USER…..) and look at the responses.
7. Type in the PORT command, giving your own IP and port number (5000). The local IP number
   can be obtained by calling program hostIP, a program that is available in your directory.

8. Type in LIST or RETR filename. Note that before repeating line 8, you need to repeat line 7.
   Moreover, you need to change the port number, because the FTP server cannot use the same
   channel twice.

                             a)                        b)     TCP channel (commands)
                                       select {

                                                                  TCP channel (data)
           XTerm2                                      c)

                                                                  TCP daemon
                                   active object

LABORATOIRE DE TÉLÉINFORMATIQUE                         Communication Software Engineering

An HTTP server for a specific application

This exercise shows how to specify and implement an application that uses an automaton. The
example will devise a service based on HTTP, the basic protocol of the web. It will use text fields and
buttons on HTML pages, whose values are returned by the client to the server by means of the POST
command, when the user of the browser has typed its data in the fields.

Part 1: Introduction to the HTTP Protocol

When a WWW browser is requested to get the content of an URL, it sends a text starting with the
symbol GET, followed by the name of the designated file to the indicated station, at port number 80
which is the default value (actually we will use 8080 for the tests). The server gets the file name and
returns its content through the TCP channel that has delivered the GET command.

The text below is a complete HTML page containing some fields and buttons that the user can fill in
or click respectively. When the user has filled the form and s/he clicks the button Submit that appears
on the page, the browser sends automatically a text containing the data prepared by the user to the
address mentioned in the FORM command. Some explanations follow the text.

   1    <html><head><title>Sondage</title></head>
   2    <body>
   3    <h1>Sondage</h1><hr>
   4    <form METHOD="POST" action=
   5         "" >
   6    <h3>Enter your identity :</h3><br><P>
   7    <input name="m_NAME" size=25>
   8    <input name="m_FIRST" size=25><P>
   9    <input NAME="TEST" type=radio value=YES> yes /<P>
  10    <input NAME="TEST" type=radio value=No>No<P>
  11    <input type=submit value=submit>
  12    <input type=reset value="resets text and buttons">
  13    </form><hr>
  14    </body>
  15    </html>

All commands concerning the data fields (texts and buttons) must be placed between the marks of the
FORM command (lines 4 and 13). Line 4 specifies that the answers will be sent under the format
POST (another format is based on command GET). Lines 7 and 8 create text fields that may be filled
in by the user. Lines 9 and 10 create buttons, both linked to the same name TEST. They act as radio
button, namely, when a button is pressed, all other buttons with the same name are reset. Line 12,
displays a button that can be used to reset all buttons and text fields of the form. When the button of
line 11 is clicked, the browser sends a text starting with the keyword POST, followed by the filename
indicated in the form command (response.html in this case, as it appears, at line 5), the text and the
buttons typed by the user in the format given below, and a few general parameters, to the address
mentioned at line 5.


Each field and name of activated button is written behind the corresponding keyword given in the

The data exchanged between the clients and the server are coded in plain text. They can thus be
displayed and read by a human. In this first part, we will display this encoding by means of program
webShowPost.scxx. The program visualizes the text sent back by the client when it returns the fields
filled in by the operator.
    1. Run the program, by typing webShowPost. ( Directory HTTP.TEST, type make install to
       create the executable binary and make clean to recover the disc space )
    2. Adapt file post.html by inserting the name of the server your are working with.
    3. Open netscape and read the following URL:, where is the name of the host on which webShowPost runs.
    4. The server displays the request it has received and sends the file indicated after the GET
       command back to the client (find GET and the file name in the displayed text). The file
       post.html returned to the browser (marked by > on the server’s display) contains a form that
       displays two text fields and two buttons. Create new files if you want to analyze other cases ! In
       particular, file cookie.html contains a few extra lines with a cookie. A cookie has a name and a
       value. Once a cookie has been sent to a client, the latter returns it each time it sends a command
       to the server that has sent the cookie. This allows for example the identification of successive
       calls from the same client. (
    5. Write something in the text fields, in the page displayed by the browser, click on the buttons
       and then on button submit. Examine the responses of the server.

Part 2 : An application that collects votes
We will now create a very simple application that collects votes from a number of users. Each user can
register her/himself with a name s/he enters, and vote on some questions, in a single session or in
several successive sessions. The authentication of the users is not addressed in this exercise. The list of
questions is stored as a constant string array in the program. The user names and the votes are also
stored in the server memory, and lost each time the program is reset. However the structure of the
program would make it easy to add all these missing features.

                                                                                            (the labels of the
                                                                     Survey (1)             arrows indicate :8080/SURVEY                    Enter your                 the button returned
                                                                 identification …
                                                                                            by the browser)
                                                                  ? result
                                                                  ? vote

     Display result (2)                                     All questions                      Display (30)
             …                                              answered (35)                         questions
                                     result                                                      ? questions
                                                                                              (store response)
                                                                        vote again

            Thank you                                        otherQuestions                  (the numbers in
                                   quit                      ? result     (12)
            (terminated)                                                                     the states are
                                                             ? vote again                    related to the
                                                             ? quit
                                                                                             following pages

                     Figure 1. Automaton representing the functioning of the server.

The functioning of the program is described in Figure 1 with an automaton. In each state, a web page
(or part of a page) is displayed. The transition from one state to the next depends on the response
returned by the client. Each page is shown in one of the following sections, both as it appears on the
screen, and in ASCII form. The content of some pages are defined as constant strings in the server, but
the contents of others are created on line, according to the information stored in the server’s memory
at the time of the page creation. The origin of the different page parts are indicated beside the ASCII
texts. The numbers in the headers on page 6 and on the following ones correspond to the numbers in
the states of the automaton.

Note : The TCP channels remain busy for a while when they have been used and not closed correctly.
They cannot be reopened at once, because otherwise, it may happen that a bloc from the previous
transfer may have been slowed down by congestion, and be taken as a bloc of the new transfer when it
arrives. Thus each time the server is cancelled, it must await the commands on a new channel. The
program reads the hostname and the port number on its command line. Start the server with

        SurveyMonoServer 8081             then 8082, 8083…

incrementing the port number at each new execution. Remember to update the port number in the
browser too.

Exercise 1

The file SurveyMonoServer.scxx contains all elements needed to create the program. The only missing
part is the automaton, which you are proposed to restore. Build the automaton piecewise, checking the
states and transitions each time a new one is built.

Functions and objects available

void getName(char *buff, char *nameToGet, char *returnName)
This function gets the symbol that is located just after the string nameToGet in the buffer buff. The
symbol is returned in parameter returnName .

i = testName(char *buff, char *tests[], int n)
Function testName returns value 1, 2 or …, depending on what string lays after the symbol stored in
the first position of the array of character strings passed in tests. If this parameter has the value
defined below, the function returns 1, 2 or 3, when "RES", "VOTE" or "FIN" respectively is placed
after "m_VOTE_RES=" in buff. It returns –1 if none of the strings exists.
char* tests[] = {"m_VOTE_RES=", "RES", "VOTE", "FIN"};

The object votesBuff keeps the names typed in by the users and all the votes of each person. It defines
the following methods, which can be used to handle the actions defined above:

      i = votesBuff.getPos(char* nameP)
      This method gets the position of a person by its name. If the person is not already registered, it
      is inserted into a free slot in the table. This method can thus be used to introduce a new name
      into the local database. If there is no place any more, the function returns –1.

      votesBuff.setVote(int pers, int quest, int val)
      This method sets the value of the votes of person number pers on question quest. The value
      of the vote is passed in val (0 or 1).

      votesBuff.yesNoNumber (int nQ, int &a, int &b)

      This method returns the number of yes, and the number of no votes to the question nQ, in its
      two last parameters.

      char* str = votesBuff.getName (int pers)
      This method gets the name of a person identified by its number, out of the local database. (Note:
      the previous getName extracts the name from the message read from the network).

      void getBufferEnd ()
      This function reads the end of the buffer, namely the part that remains to be read after a first
      block of data has been read.

Server servicing several clients simultaneously

As all commands are sent to the same port, they arrive at the same TCP daemon. However, it can
happen that the path used by a client is congested, while the paths of the other clients are not. Thus, in
order not to block all clients if one client is slowed down, all clients must be handled concurrently,
with one active object (connection server) per active client.

The connection servers are controlled by the main, which now gets only the first block of data each
time a new TCP channel is opened, checks if these data belong to an active client (which has already
begun to go through the automaton) and depending on this check, either instanciate a new connection
server or passes the data already read to the corresponding connection server. The active objects are
depicted in the dataflow diagram on Figure 2.

At the first call of a client to the daemon, a new connection server is instantiated, and a new
identification (A00000, A00001, A00002…) is computed, stored in array servers and sent back to the
client in the form of a cookie. The index where the name has been stored is passed to the connection
server. At the end of a session, the connection server clears its connection name in the table and
deletes itself (delete this). The automaton of Figure 1 is implemented in the connection servers.

As seen in Figure 2, the connection servers access distinct elements stored in an array of passive
objects (rectangles). Note that if several servers would access the same element in one of these arrays,
additional protection should be added, but it is not the case here.

             Daemon                               Connection server
             handler                                Connection server                 Names
                                                      Connection server               and vote
                                    servers              handleConnection()
                                   tion IDs
             daemon                                        TCP socket          instanciation

                                      Figure 2. Dataflow diagram

Once created, a connection server waits for the main to call it on the handleConnection() method. This
method copies the data already read by the daemon into the connection server’s buffer and transfers the
socket address into data member soc of the connection server. The connection server then waits for the

remaining data coming from the socket it has received in the handleConnection() call by means of a call
to the private method getBufferEnd(). The length of the message is written on a line of the incoming
data, as can be checked with the webShowPost program.

The connection server then analyzes the received data and decides, from the data typed in by the user,
and the indications of the automaton defined in Figure 1 into which state to jump. It then sends the text
of the next page into the current socket. The end of the data sent to the browser are indicated by closing
the socket (delete soc).

In brief: when the daemon receives the GET command from the browser, it creates a new connection
server. The latter obtains the whole command sent by the client, by accepting method
handleConnection, called by the main when the answer has arrived. The connection server then calls
getBufferEnd() to get the whole message. When the data are complete, the first page is sent back and
the connection server accepts handleConnection and calls getBufferEnd() again. When the new data
have arrived, the name of the browser user is extracted, and the buttons clicked by the user are
checked to know what to do next.

Exercise 2

Complete the main by adding the handling of the connections. When a GET command arrives, the
server creates a new name and sends a cookie with this name. When a POST command arrives on this
server, it checks which connection server services the user that returns that cookie. The relationship
between the cookie names and the connection servers is saved in the array servers.

Functions and objects available for the multi-server
void handleConnection(TCPSocket* soc, char* bf, int lnBuf)
This method is called by the daemon server. It must be accepted by the connection server as soon as it
is ready to get the next message.

myID    Local attribute containing the number attributed to this server.

servers[myID].name[0]=0 Cancel the connection.

Page 1

<body BGCOLOR="#FFFFFF"><h1>Survey</h1><hr>
<form METHOD="POST" action="">
<h3>Enter your identity :</h3>
<br><P><input name="m_NAME" size=25><P>
<input NAME="m_VOTE_RES" type=radio value=RES>
You want to see the result of the votes<P>
<input NAME="m_VOTE_RES" type=radio value=VOTE>
You want to vote<P><input type=submit value=Submit>
<input type=reset value=Reset><P></form><hr>

Page 2

<html><head><title>Survey</title></head>               < string page2
<h1>Here are the results of the survey</h1><hr>
 0 yes, 0 no --- Are you in favour of a football       < vote + questions[1]
tournament ?<P>
 1 yes, 0 no --- Are you in favour of a walk in the    < vote + questions[3]
 0 yes, 0 no --- Would you like to try a bungy-jump?   < vote + questions[5]
<form METHOD="POST"                                    < string page10
<hr><P><h3>Your name: aaaa</h3>                        < votesBuff.
<input NAME="m_VOTE_RES" type=radio value=RES>         < string page11
Do you want to see the result of the votes<P>
<input NAME="m_VOTE_RES" type=radio value=VOTE>
Do you want to vote on more questions ?<P>
<input NAME="m_VOTE_RES" type=radio value=FIN>
Do you want to quit ?<P>
<input type=submit value=Submit>
<input type=reset value=Reset><P>

Page 30

<html><head><title>Survey</title></head>               < string page30
<h1>Please answer some or all the questions
<form METHOD="POST" action="
<input NAME="m_Foot" type=radio value=YES>Yes /        < questions[0]
<input NAME="m_Foot" type=radio value=NO>No
--- Are you in favour of a football tournament ?<P>    < questions[1]
<input NAME="m_Alps" type=radio value=YES>Yes /        < questions[2]
<input NAME="m_Alps" type=radio value=NO>No
--- Are you in favour of a walk in the Alps?<P>        < questions[3]
<input NAME="m_Bungy" type=radio value=YES>Yes /       < questions[4]
<input NAME="m_Bungy" type=radio value=NO>No
--- Would you like to try a bungy-jump?<P>             < questions[5]
<input type=submit value=Submit>                       < page31
<input type=reset value=Reset><P>

Page 35

<html><head><title>Survey</title></head>              < string page35
<body BGCOLOR="#FFFFFF"><h2>You have answered all
<hr><P><h3>Your name: aaaa                            < votesBuff.
</h3><input NAME="m_VOTE_RES" type=radio value=RES>   < string page11
Do you want to see the result of the votes<P>
<input NAME="m_VOTE_RES" type=radio value=VOTE>
Do you want to vote on more questions ?<P>
<input NAME="m_VOTE_RES" type=radio value=FIN>
Do you want to quit ?<P><input type=submit
<input type=reset

Page 12

<html><head><title>Survey</title></head>          < string page12
action=" ">
<hr><P><h3>Your name: aaaa</h3>                   < votesBuff.
<input NAME="m_VOTE_RES" type=radio value=RES>          getname(iPers)
Do you want to see the result of the votes<P>     < string page11
<input NAME="m_VOTE_RES" type=radio value=VOTE>
Do you want to vote on more questions ?<P>
<input NAME="m_VOTE_RES" type=radio value=FIN>
Do you want to quit ?<P>
<input type=submit value=Submit>
<input type=reset value=Reset><P>


<html><body BGCOLOR="#FFFFFF"><P>
Thank you for your participation<P><P>
<a href=" ">
Another vote or result ?</a>
<P><a href="">
You may want to see the EPFL page</a>

LABORATOIRE DE TÉLÉINFORMATIQUE                          Communication Software Engineering

Deadlock in a Distributed Application

This exercise shows how to analyze a distributed application to detect if it is free of potential

For that purpose, we consider a distributed system that allows a group of users to see, on their
own display, a shared drawing that they all edit simultaneously. In order to assure that all
commands are processed in the same order, the system has a central monitor that collects the
commands sent by the users and broadcasts them back. Even the commands that come from
the local user pass through the monitor before being applied locally, so that all figures are
drawn in the same order. In this exercise, we will only analyze the structure of the application
without any internal details because the deadlock only depends on the ordering of the actions.

The first version will simulate an application run locally. Its communications will thus be
made by rendezvous. In the second version, the connections between the users and the
monitor will be made by simulated remote procedure calls similar to the one defined by the
standard CORBA. This will allow us to test the system in a local environment, and be sure
that it cannot deadlock when it is run under its distributed form.

Definition of the distributed application (local mode)
Each user can press a button to simulate the request of a specific action. This action is
announced to the monitor that broadcasts it to all users, including the initiator. Each user
accepts the calls from the monitor in parallel with the click on the button. Figure 1 shows the
dataflow diagram of this application.

                  User        broadcastCommand                         Monitor



                  User        broadcastCommand

This system is given below :
           active class User {                 // user definition
              int j;
            CentralMonitor* mon ;
              void init(CentralMonitor* mon)   // initialization
                { this->mon = mon ; }
              User() { j=0 ; }                 // constructor
              void broadcastCommand(int n) {   // entry point offered by the
                printf ("%d\n",n);             // user to get its broadcast
              @User ();                        // body definition,
           };                                  // its content is defined below

           active class CentralMonitor {      // server definition
              int m;
              void init(User *C1, User *C2, User *C3)
                { this->C1=C1 ; this->C2=C2; this->C3=C3; }
              void accessMonitor (int m1) {   // entry point where the monitor
                m = m1;                       // awaits the user calls
              @CentralMonitor ();

           User::@User () {                   //    user implementation
             accept init ;
             for (;;) {
               select {                       //    the user awaits a local
                  waituntil(now()+rand()%100);//    command in parallel with
                  j = (j+1)%4
                  S->accessMonitor (j);
                  accept broadcastCommand;    //    the reception of its own
               }                              //    part of the broadcast

           CentralMonitor::@CentralMonitor(){// monitor implementation
             accept init ;
             for (;;) {
               accept accessMonitor;         // the monitor accepts a command
               C1->broadcastCommand(m);      // and sends it to all users

           CentralMonitor S;                   //   instanciation of the
           User C1, C2, C3;                    //   active objects
           S.init(&C1, &C2, &C3) ;             //   transmission of their
           C1.init(&S) ;                       //   partner’s address and start
           C2.init(&S) ;
           C3.init(&S) ;

Exercise 1 :

Analyze this system to check if there are potential deadlocks. It is stored in program
deadlDistr.scxx. If you find deadlocks, fix the problem.
The system can be analyzed with two means: random walking or reachability analysis.

To control a program with the monitor, create it with make deadlDistr. The random walker is started
from the Monitor. To start the latter, type Monitor. Click File / Load program to test…, give the
program name in the corresponding field, type your host name, set the sC++ button and finally click
the Ok button to load the program. Click Uniform Random Walk in the menu Simulator and use the
various items of menu Execution to control the execution of the program. Be patient, the monitor
needs some time to scan all files and to display the windows ! Click Execution / Show Event History
to get a chart of the execution.

Application (distributed mode)

Define the simulation of a distributed version of the corrected version, and verify again if
there are potential deadlocks in this new version. The communication implementing the RPC
(remote procedure calls) can be instantiated from the following class:

       active class RPC {                              //   This class represents
        public:                                        //   all what is stored between
         void accessMonitor(int m){                    //   the user and the monitor:
           S->accessMonitor(m);                        //   the stub, the skeleton and
         }                                             //   the TCP/IP channels
         @RPC () {
           for (;;) {
              accept accessMonitor;
       } } };

The program must intantiate an RPC object between each user object and the monitor, and the
users must now call the RPC objects rather that the monitor directly. Similar channels can be
built for the broadcasts from the monitor, but a deadlock may already happen with the use of
the RPC in a single direction.

Exercise 2 :
Introduce the RPC between the user and the monitor in the file named deadlRPC.scxx, which
contains a deadlock free implementation and a definition of a simulated RPC channel. Verify
that the RPC does not introduce a new deadlock. If it is the case, fix the problem, by
separating the command accessMonitor into the two commands post_accessMonitor and
ready_accessMonitor defined in file deadlRPC.scxx allowing the execution of the RPC in
asynchronous mode. (Insert the call to post and the waiting for the ready command in a finite
state machine that accepts the broadcast call in every state.) Verify that the new solution
functions correctly.

LABORATOIRE DE TÉLÉINFORMATIQUE                          Communication Software Engineering

A distributed editor

This exercise studies how to implement the communications defined in the previous exercise, in a
CORBA environment. A graphical editor decomposed in two parts is provided. The active objects of
the first part deliver the parameters of the figures created by the user (segment, circle or rectangle) on
the drawing area. The second part, given as a passive object, offers possibilities to draw the figures.

Figure 1, gives the detail of the editor program, with an exchange object that makes the connection
between the two parts of the graphical editor.

                                              drawing area



                           mouse clicks

                    ActiveObject                 start / stop               Exchange

                                     Figure 1. Dataflow of the editor

Object Exchange is listed below:

        1      class remCommand {     // defined in dataStruct.h
        2      public:
        3         int type;
        4         double v1X, v1Y, v2X, v2Y, r;
        5      };

        6          for (;;) {
        7            create_fig->Get(&comm);
        8            displayGr->figure(&comm);
        9          }
       10      }

Line 7 awaits the next drawing request made by the user. The line 8 uses the passive object displayGr
to display the figure obtained in comm (This program is stored in whiteBoard.scxx)

Exercise 1 :

Create a user, in editorUser.scxx (part of the program is available) that gets the commands sent by a
user and returns them back to the user for displaying. Define a single user, but in such a way that it is
compatible with several users, according to the schema given in Figure 2. The monitor and its header
(editorCentralMon itor.scxx, editorCentralMonitor.h), as well as a main (editorMain.scxx) are also

available. The monitor offers the post_accessMonitor() and ready_accessMonitor() methods to avoid

The commands exchanged between the user and the monitor have the following form, where the
integer identifies the type of the command (segment, rectangle or circle) :

        1      struct remCommand {
        2         int type;
        3         double v1X, v1Y, v2X, v2Y, r;
        4      };

This program version is purely local : the objects are connected by rendezvous.

                            drawing area

                                                   segment                   local rendezvous
                                                   circle                   or network
      mouse clicks                                                       CORBA connection

                                                                  User_i                    CentralMonitor_i
ActiveObject                      start / stop             broadcastCommand

                              Figure 2. Definition of the Corba interfaces

Exercise 2 :

Transform the local implementation into a distributed one. This is done by using the CORBA library.
The IDL description of the interfaces of the services that can be called in the monitor and in the user
are defined below. The corresponding element that create Actually both the monitor and the user have
client and server functioning. We will thus insert all interface classes used on both side in the same
interface, but instantiate on each side only the needed interfaces. The post_ and ready_ versions are
generated automatically, but only the simple version appears on the server side.

IDL description of all interfaces :

        1      struct remCommand {
        2         long type ;
        3         double v1X, v1Y, v2X, v2Y, r;
        4      };
        5      interface CentralMonitor {
        6         boolean connect (in string userIOR);
        6         void accessMonitor (in remCommand comm);
        7      };
        8      interface User {
        9         void broadcastCommand (in remCommand comm);
       10      } ;

The IDL compiler generates the following files from the definition above, assuming that it is contained
in a file named editorDistr.idl. The table also shows the files that were used in the previous exercise.

                      Generated by the IDL compiler From the previous exercise
                      editorDistr_CORBA.h           editorGraph.h
                      editorDistrclt_Clt_Main.scxx  editorUser.h
      editorDistr.idl                               editorUser.scxx (<-new main)
                      editorDistr_Impl.h            editorCentralMonitor.h
                      editorDistr_Impl.scxx         editorCentralMonitor.scxx (<-new main)
                                                    editorMain.scxx (disappears)

We need client and server interfaces in both the users and the central monitor, but as we have only one
IDL description file, we must extract the relevant parts out of the generated files and modify the files
editorUser.scxx and editorCentralMonitor.scxx, and their headers accordingly. The new mains will be
integrated in editorUser.scxx and editorCentralMonitor.scxx, which will become the new user and the
monitor executable files. We will instantiate only one user, the generalization to several users joining
and leaving the editor being programming as usual. We will include the whole stub and skeleton code
(editorDistrclt_Stub.o, editorDistr_Skeleton.scxx.o) in both the users and the central monitor, and only
instantiate the needed interfaces in each file.

The central monitor is registered in the name server, but not the users. The users pass their own object
id (IOR) to the central monitor by means of the connect RPC, so that it can broadcast the data back to

Figures 3 and 4 show the structure of the each end of the distributed application.

 defined in                                                      defined in editorDistr_Stub.scxx
 editorDistr              BASE_User
  _Skeleton                                                                                             TCP/IP
                                 User_i                            CentralMonitor_Stub
                               (client role)
                                                                   connect                              TCP/IP
 defined in
 editorDistr               broadcastCommand
  _Impl                    (server role)                           accessMonitor

                instantiation defined in                                        instantiation defined in
          editorDistr_Impl_Main.scxx                                            editorDistr_Clt_Main.scxx
          ---- Binding User ----                                                --- Resolving CentralMonitor ---
           (do not insert name in          #include ”editorDistr_CORBA”.h
            Name Server)                   #include <CosNaming.hh>
                                           main() {
                                             instantiations / initializations

        Figure 3. Structure of the User (All these parts must be stored in editorUser.h / .scxx)

Steps to execute in this exercise

1. Copy the editor* files into the CORBA subdirectory and compile the editorDistr.idl file with the
   IDL compiler.
2. Complete the definitions contained in editorUser.h and editorCentralMonitor.h, so that objects
   defined in these files can play the role of server implementation: Add the include files, the
   inheritance of the BASE (=BOA + skeleton) and the constructor parameters, according to
3. Make the following modifications to editorUser.scxx :
    – Add the parameters of the constructor and the initialization of BASE, as in editorDistr_Impl_
    – Add the main read from editorMain.scxx and keep only the initialization of activeObject, the
      other objects must be instantiated withe the server function.
    – Introduce the initializations of the ORB and the name service read from editorDistr_Clt_
      Main.scxx in the main of editorUser.scxx.
    – Initialize the stubs pointing to the central monitor (Resolving Central Monitor) as in
      editorDistr_Clt_Main.scxx, still in the same main. Give a name of yours to the central monitor.
    – Instantiate a user implementation as in editorDistr_Impl_Main.scxx (but do not bind its name
      in the name server).
    – Pass the CentralMonitor stub pointer into the user implementation (declare the pointer in the
      user definition, as a parameter in the constructor and initialize it in the constructor).
    – In the code of the user implementation, get the IOR of this object and send it to the central
      monitor by means of the monitor_ptr ->connect() primitive (monitor_ptr is a stub pointing to
      the central monitor). The following statements get the user IOR
      from inside the user object :
               CORBA::Environment env;
               CORBA::Object_ptr myPtr;
               CORBA::String myIOR;           // ! it is a pointer
               myPtr = this->_this();
               myOR = orb_ptr->object_to_string (myPtr, env);
   orb_ptr is the standard pointer to the ORB, defined in the main. Pass it to the user implementation
   in the same way as the central monitor stub pointer.
4. Make the following modifications to editorCentralMonitor.scxx :
    – Add the parameters of the constructor and the initialization of BASE, as in editorDistr_Impl_
    – Introduce the initializations of the ORB and the name service read from editorDistr_Clt_
       Main.scxx in a main added in editorCentralMonitor.scxx.
    – Instantiate a CentralMonitor implementation as in editorDistr_Impl_Main.scxx. Change the
      name bound in the server with the name of yours chosen above.
    – Add the code of the connect primitive in the CentralMonitor implementation. Read its code
      from editorDistr_Impl.scxx and complete it to save the incoming string .
                 s1 = CORBA::string_copy(s2)
      create an object from this string
                 CORBA::Environment env;
                 CORBA::Object_ptr tmp;
                 User_stub_ptr user_ptr; // User_stub_ptr is defined in editorDistr_Stub.scxx
                 tmp = orb_ptr->string_to_object ( s1, env );
                 user_ptr = User_stub::_narrow ( (CORBA::Object_ptr) tmp );
5. The IDL compiler also generate the Makefile if there are none. The one that is in your directory
   has been adapted to have it link-edit your programs instead of the ones generated by the compiler.
6. Compile and launch the central monitor and a user.
7. If you want to handle several users, complete the programs correspondingly.

defined in                                                  defined in editorDistr_Stub.scxx
editorDistr               BASE_CentralMonitor
                                (client role)
defined in
                                                                     User_Stub                   TCP/IP
 _Impl                     accessMonitor                           broadcastCommand
 .scxx                     (server role)

   Instantiation defined in
   -------- Binding CentralMonitor --------
    ( including name insertion                                             Instantiate a stub pointing to
     in Name Server )                                                      the user from its IOR, sent by
                                #include “editorDistr_CORBA.h”              method connect :
                                #include <CosNaming.hh>
                                main() {                                   string_to_object(userIOR,env) ;

              Figure 4.   Structure of the central monitor
                          (All these parts must be stored in editorCentralMonitor.h / .scxx)


Shared By: