To Cliser Home

Cliser Examples: A Random Quote Service using UDP over TLI

To Cliser
Architecture


As an example of a non-standard service, we will in this example write a server that provides a randomly-selected quote from a file of quotes, and a client to read and display a quote from the server. Providing this service should not take very long, and so we will use the UDP communications protocol, single-threading, and C++.

For lack of a better number, our server will use port 9876. Its constructor will read the quotations from a data file, and store them in a vector of strings named quotes. When it receives a message from a client, our server will simply generate a random integer i in the range of valid vector indices, and then send to the client the string in quotes[i].

A UDP random quotes client thus sends a message to a random quotes server, and then reads and displays the server's reply.

To build a client and server for the daytime service, we follow the steps described previously:

1. Use Cliser

1a. Run Cliser.

The nicest interface for Cliser is a graphical user interface written in Java. To run it, enter:
  $ java cliser.GUI
This will display the Cliser graphical user-interface, as shown below:

1b. Enter Parameters.

We then enter the name of our service (RandomQuotes), the port is should use (9876), and the protocol we want to use (UDP); indicate what we want to generate ( both a client and a server), specify the language we want to generate (C++), the network interface we want to use (choose one appropriate for your OS/platform -- we'll use AT&T Unix TLI here), and the kind of server we want (Iterative/single-threaded).

1c. Generate Source Code.

In the GUI interface, we then click the Generate button. This generates the files RandomQuotes_UDP_TLI_Client.cpp and RandomQuotes_Iterative_UDP_TLI_Server.cpp. We then click the Quit button to quit using Cliser.

2. Customize the Source Code

Since we are building both a client and a server, we must customize both of the files generated in the previous step.

2a. Customize the Server

Using our favorite text editor, we
  1. open the file RandomQuotes_Iterative_UDP_TLI_Server.cpp
  2. #include the necessary libraries (e.g., <vector>) and define a myQuotes attribute variable in class RandomQuotes_UDP_TLI_Server:
        private vector<string> myQuotes;
      
  3. add code to the constructor to initialize myQuotes:
    RandomQuotes_Iterative_UDP_TLI_Server::RandomQuotes_Iterative_UDP_TLI_Server(int port)
     : Iterative_UDP_TLI_Server("RandomQuotes", port)
    {
      ifstream fin("quotes.txt");
      string quote;
      for (;;)
      {
        getline(fin, quote);
        if ( fin.eof() ) break;
        myQuotes.push_back(quote);
      }
      fin.close();
    }
    
  4. replace the comments in method RandomQuotes_Iterative_UDP_TLI_Server::interactWithClient() with statements that provide the required behavior:
      void RandomQuotes_Iterative__UDP_TLI_Server::interactWithClient()
      {
        int randomIndex = rand() % myQuotes.length();
        string discard;
        this->receive(discard);
        this->send(myQuotes[randomIndex]);
      }
      
  5. Using a text editor, create a data file of quotes (quotes.txt) that the constructor expects to find:
        No matter where you go, there you are. -- Buckaroo Banzai
        To be or not to be, that is the question.  -- Shakespeare (Hamlet)
        Mein Fuehrer, I can walk!  -- Stanley Kubrick (Dr. Strangelove)
      
Our server customization is this simple because of the Cliser system architecture which, among other things, provides the easy-to-use, protocol-independent send() and receive() communication primitives.

Note that because the UDP protocol is connectionless, our method must get (and discard) a message from the client before it can know the client to which the random quote must be sent.

The result is the file RandomQuotes_Iterative_UDP_TLI_Server.cpp.

2b. Customize the Client

Again using our favorite text editor, we open the file RandomQuotes_UDP_TLI_Client.cpp and replace the comments in the body of method RandomQuotes_UDP_TLI_Client::interactWithServer() with statements that define the required behavior:
  void RandomQuotes_UDP_TLI_Client::interactWithServer()
  {
    string quoteReceived;
    this->send("Hi");
    this->receive(quoteReceived);
    cout << quoteReceived << endl;
  }
The result is the file RandomQuotes_UDP_TLI_Client.cpp. As was the case with our server, our client customization is straightforward thanks to Cliser's simple send() and receive() communication primitives.

3. Compiling and Linking

Once we have customized the files generated by Cliser, we can compile each as we would any other C++ program file. On a system using BSD or TLI, we might use the automatically generated Makefile When executed via make, this file creates the binary executable files RandomQuotesd for the server ('d' stands for 'daemon'), and RandomQuotes for the client. Because Cliser-generated clients and servers are derived from classes in the Cliser class library you must have the cliser header and library files installed in folders/directories on your system and inform your compiler and linker of their locations. (The generated Makefile uses the default installation directories).

4. Deploy and Run

To deploy your client, copy its binary executable file to a directory that is listed in the PATH variable of your users (e.g., /usr/local/bin). If you wish for your users to be able to execute your server (maybe not such a good idea, unless you want lots of redundant servers running on your system), it can be deployed the same way.

4a. Running the Server

You can run the server (as the system administrator) as follows:
  $ RandomQuotesd
The server can also be run using another port, as shown in the other examples.

4b. Running the Client

If your server is using port 9876 on the machine myMachine.myDomain, you can run the client to it with:
  $ RandomQuotes myMachine.myDomain 
If your server is using a different port, that port can be specified via a command-line argument, as shown in the other examples.

A sample client session might be as follows:

  To be or not to be, that is the question.  - Shakespeare (Hamlet)


Up to the Cliser home page Up to the Examples A UDP Client/Server for a standard Daytime Service using Java A TCP Client/Server for the standard Echo Service using C++ over BSD A TCP Client/Server for the standard Echo Service using C++ over WinSock A TCP Client/Server for a Knock-Knock Service using Java


This page maintained by Joel Adams.