UNX511/DPS912 - Lab 9: Server with Multiple Clients and a Receive Thread with Mutexing

Due: Sunday, August 4, 2021

NB: Due to the length and complexity of this lab, this lab will be considered as two labs. Meaning, this lab is worth 2% of your final mark.

In this lab you will create a server (server.cpp) that communicates with three clients using a receive thread for each. The client code has been given to you along with the Makefile, a start-up script, and a stop script in case you have to manually stop all the clients. You can retrieve these from the following links:
client.cpp,
Makefile,
startClient.sh,
stopClient.sh.

Your server will use non-blocking stream sockets in the internet domain. Your socket will bind to the localhost (127.0.0.1) and the port number will be specified from the command line. For instance, if you want to use port 1153, you would start your server and clients with:
$ ./server 1153
$ ./startClient.sh 1153

Be sure to start your server first. You will probably want to start your clients in another window.
startClient.sh will start three clients with a 1 second delay between each.

Once your socket is bound, you will listen for connections. Be sure to distinguish between the master file descriptor and the connection file descriptors for each of the clients. You will have one master file descriptor for listening and accepting, but three connection file descriptors for each of the three clients.

Once a client connects, you will start off a receive thread to service all socket reads from this client. In this way you avoid using the select()function. Be sure to pass through the connection file descriptor for that client to the thread as a parameter. This means your socket reads and writes are no longer synchronized as before. They are asynchronous. You will perform socket writes from your main() function and socket reads from your receive threads.

The receive thread will change the options of its connection socket to set a read timeout of 5 seconds. Documentation on how to do this can be found at:
setsockopt - Linux man page,
Chapter 61 page 624 of the text Advanced Programming in the UNIX Environment, and
the article Linux: is there a read or recv from socket with timeout?.

Since communications are now asynchronous, the server does not have to instruct the client to send data. As soon as the client connects to the server, the client will start sending data (see client.cpp).

When a client sends text to the server, the server will read the data in its receive thread and push it into a message queue. The message queue could be of type:
queue<string> message;

The main() function, in its infinite while-loop, will test for new connections with a non-blocking call to accept(), and write the contents of the message queue to the screen if there is anything in the message queue. If the queue is empty, main() will sleep for 1 second and check the queue size again. Be sure to pop the message off the message queue once you have written it to the screen.

The infinite while loop (conditioned on is_running) in main() should look something like this:

The receive thread should look like this (the same code can be used for all three clients):

The communications stop when a ctrl-C is issued to the server. The signal handler for the server will set is_running to false causing the infinite while-loops in the receive thread and in main() to end. The server in its main() function will then send "Quit" to each client, close all connections, and exit. The clients will interpret "Quit" to mean it is time to finish and they will shutdown as well. Be sure to join the receive threads to main() before main() exits and be sure to close all connection file descriptors, as well as the master file descriptor.

Questions

  1. What is the difference between synchronous and asynchronous communication?
  2. Do you prefer socket reads in a receive thread or do you prefer both socket read and write to be in the main() function? Why?

Lab Submission:

Please embed your answers to the questions in server.cpp and mail your server.cpp to: shahdad.shariatmadari@senecapolytechnic.ca