A Survey System

The goal of this exercise is to develop a client/server application for making surveys over the Internet. A survey will be composed of the following elements:

Here is one possible example:

The server will store a list of surveys that some administrative user (identified with a password) will have created. Clients will connect to the server and vote for the choices. The server will store, in addition to the question and the choices, the following information:

The client and server applications will have a text (console) interface.

Client

The client will first connect to a server right after it starts. The IP address and port are given as commandline parameters. Here is what you would see on the terminal:

C:\Users\Telecom> Client.exe 10.20.30.40 1234

We are using the Windows console, we are inside the folder C:\Users\Telecom and we run the client, providing the IP address and port of the server.

If the client fails to connect to the server, it will show an error message and terminate. If it succeeds, it will show the following menu:

0. List all surveys and statistics
1. Vote in one survey
2. Create a survey (admin only)
3. Remove a survey (admin only)
4. Exit

Choose an option :

If the user chooses an option different from 0 to 4, the client will show an error message and display again the menu.

The last option terminates the client. The first 4 options allow the user to do the following:

Option 0 - List all surveys and statistics

When the user selects this option, the client will request to server for the list of surveys defined in the server, together with the number of votes that each choice received. The client will display the data using the following format:

Question 0: What is your favorite programming language?
- Choice 0 ( 5 votes,  25%): Java
- Choice 1 ( 5 votes,  25%): C#
- Choice 2 (10 votes,  50%): Python

Question 1: What grade you think you will get on the .NET course?
- Choice 0 ( 5 votes,  33%): Less than 12
- Choice 1 (10 votes,  66%): More than 12

Question 2: Do you know what is a critical section?
- Choice 0 ( 8 votes, 100%): Yesssss!
- Choice 1 ( 0 votes,   0%): No :(

Option 1 - Vote in one survey

The user has typed 1 and now the client shows the menu to vote. In the following example the user will select the question number 2 and will vote for the choice 0 to that question:

Ok, choose a question to vote for:

Question 0: What is your favorite programming language?
Question 1: What grade you think you will get on the .NET course?
Question 2: Do you know what is a critical section?

Choose a question: (the user enters 2)

Question 2: Do you know what is a critical section?
- Choice 0: Yesssss!
- Choice 1: No :(

Choose a choice: (the user enters 0)

Thank you, you voted 0 on question 2!
Sending the data to the server... Done!

After the client gets the choice from the user, it will send it to the server. Observe that, to implement this menu you will have to retrieve from the server the list of surveys and options currently defined in the server.

Option 2 - Create a survey

After the user selects this option, the client will ask for a password. The password will be sent to the server together with the data defining the survey. If the server accepts the password, the survey will be created and the client will indicate so to the user. If it is not accepted, the client will show an error message and come back to the main menu.

This is example execution, where the user creates a new survey with 3 choices:

Question : (the user types "How many planes orbit around the Sun?")
Choice 0 : (the user types "7 planets")
Choice 1 : (the user types "9 planets")
Choice 2 : (the user types "Not even NASA really knows...")
Choice 3 : (the user just types Enter)

Password: (the user types "admin")

Sending the data to the server... Done!

If the password is wrong, the server will send an error message to the client, and the client will show something different on the last line:

Sending the data to the server... ERROR, password not accepted :(

Option 3 - Remove a survey

Similarly to the previous option, the client requests for a password and sends it to the server. If its accepted it asks the user to provide the number of the question to remove. In the following example the user provides wrong data, and the client asks again:

Which question should I remove ?

Question 0: What is your favorite programming language?
Question 1: What grade you think you will get on the .NET course?
Question 2: Do you know what is a critical section?
Question 3: How many planes orbit around the Sun?

Choose a question: (the user enters 123)

Sorry, 123 is not a valid question id.
Which question should I remove ?

Question 0: What is your favorite programming language?
Question 1: What grade you think you will get on the .NET course?
Question 2: Do you know what is a critical section?
Question 3: How many planes orbit around the Sun?

Choose a question: (the user types 0)
Password: (the user types "admin")

Sending the data to the server... Done!

Server

The server will be a multithreaded application. Whenever a client connects to the server, the server will spawn one thread to handle the client. That thread will read and write the data socket used to communicate with the client. It will also read and write the list of surveys stored in the server. Observe that the list is shared among all the threads that handle the currently open connections to the server, so you will need to use appropriate synchronization primitives to avoid unexpected results when you update the shared data structures.

The server will be capable of replying to 4 different requests:

The server will operate as follows:

  1. The server is started.
  2. It displays on the console the IP address and port number on which it listens.
  3. It then executes (in an infinite loop) the following actions:
    • Accept a new client.
    • Create a thread to deal with it

The thread will be responsible for one client. It will access data structures shared with other threads (who deal with other clients). The thread will operate as follows:

  1. Wait for a client request. If the client closes the connection, then the thread will close the connexion and terminate.
  2. Parse the request from the client.
  3. Perform the necessary actions on the server's data structures (listing surveys currently open, votes within given survey, create/remove surveys)
  4. Send a reply to the client.
  5. Close the connexion.

Final remarks