To Cliser Home

Cliser Examples: TCP/IP (TCP) Echo Service over BSD Unix

To Cliser
Architecture


Echo is a standard TCP/IP service used primarily for testing reachability, debugging software, and identifying routing problems. The service is defined for both the TCP and UDP communication protocols. In this example, we will build a client and server for the echo service in C++ using TCP.

An echo server listens for clients on port 7. When it receives a message from a client, an echo server simply transmits the message it received back to the client. A TCP (connection-oriented) echo server continuously echoes what the client sends it until the connection is closed.

A TCP daytime client thus connects to an echo server, reads what the user enters and sends it to the server, and then reads and displays the server's reply, until the user enters some kind of end-of-input sentinel (e.g., control-d, or the string quit).

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 (Echo), the port is should use (7), and the protocol we want to use (TCP); 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 BSD sockets here), the kind of server we want (Concurrent/multithreaded), and the kind of concurrency we want (POSIX threads):

1c. Generate Source Code.

In the GUI interface, we then click the Generate button. This generates the files Echo_TCP_BSD_Client.cpp and Echo_POSIX_Concurrent_TCP_BSD_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 open the file Echo_POSIX_Concurrent_TCP_BSD_Server.cpp and replace the comments in method Echo_TCP_BSD_Thread::interactWithClient() with statements that provide the required behavior:
  void Echo_TCP_BSD_Thread::interactWithClient()
  {
    string message;
    int numCharsReceived;
    for (;;)
    {
       numCharsReceived = this->receive(message);
       if (numCharsReceived == 0 || message == "") break;
       this->send(message);
    }
  }
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 TCP protocol is connection-oriented, and the client connection is accepted prior to the execution of interactWithClient(), our method need only define what the server does to interact with the client.

The result is the file Echo_POSIX_Concurrent_TCP_BSD_Server.cpp.

2b. Customize the Client

Again using our favorite text editor, we open the file Echo_TCP_BSD_Client.cpp and replace the comments in the body of method Echo_TCP_BSD_Client::interactWithServer() with statements that define the required behavior:
  void Echo_TCP_BSD_Client::interactWithServer()
  {
    string messageSent, messageReceived;
    const string SENTINEL = "quit";
    cout << "Enter lines of text (" << SENTINEL << " to quit)\n";
    for (;;)
    {
      getline(cin, messageSent);
      if ((messageSent == SENTINEL) || cin.eof()) break;
      this->send(messageSent);
      this->receive(messageReceived);
      cout << messageReceived << endl;
    }
  }
The result is the file Echo_TCP_BSD_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 Echod for the server, and Echo 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), it can be deployed the same way.

4a. Running the Server

You can run the server (as the system administrator) as follows:
  $ Echod
If you are not the system administrator, you can still run the server by giving a different port as a command-line argument:
  $ Echod 7007
This allows a server written for a standard service to be thoroughly tested before it is deployed. It also allows server-writers without sysadmin status to test their servers on unrestricted ports.

4b. Running the Client

You can run the client by specifying the host you want it to contact:
  $ Echo ursa.calvin.edu
or if your server is listening at port 7007 on myMachine.myDomain:
  $ Echo myMachine.myDomain 7007
A sample client session might be as follows:
  tasting, tasting     client
  tasting, tasting     server
  strawberry           client
  strawberry           server
  lemon                client
  lemon                server
  orange               client
  orange               server
  quit


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


This page maintained by Joel Adams.