For this program, you will again be modifying your TCP card dealer server to use a different technique for handling multiple clients. This time, you will be back to a single-process model, but you will use asynchronous I/O to handle messages from clients. In this context, the use of the word asynchronous means that there is no coordination between your program and the operating system regarding the timing of network-related activities. In each of the past network programs you have done, you have decided at what point in the execution of your program you would interact with the OS to do some "networking stuff". With asynchronous I/O, this will no longer be the case. Your program can be blissfully doing other tasks, and the operating system can interrupt the flow of the program to tell it to go process a network-related event.
If you remember from your architecture class, this is the software equivalent of a hardware interrupt. It is also similar to the concept of events in Java or Windows programming. You can think of one of these asynchronous interrupts as the equivalent of an event for which you have registered a handler; at the time the event occurs, your program goes of to run the event handler.
In Unix, the basic mechanism for these software interrupts is the signal. Unix defines 32 different signals that the OS can generate; these go by catchy names like SIGTERM (for the termination signal), SIGHUP (for hang-up), etc. Each of these names is just a #defined constant represtenting a number between 1 and 32. Your program can install a signal handler for any one of these interrupts in order to execute application code to deal with the condition that caused the signal to be generated. You can install multiple signal handlers if you need to deal with different signals. Remember that if you haven't installed a signal handler, the C runtime code provides a default one that is executed.
For network programs, you will be interested in SIGIO. Take a look at the information on asynchronous I/O in the Unix Network Programming Manual. I also have some more information from Advanced Programming in the UNIX Environment, 1st Ed. by W. Richard Stevens.
This version of your card dealer must use asynchronous I/O to deal with client connections. There are several ways in which this could be accomplished; one of them is to leave the server socket you create to listen for connections in normal synchronous, blocking mode, but to change every new child socket to asynchronous non-blocking mode. Then you can implement a SIGIO handler that will only need to deal with client requests, and the main program loop can do a normal blocking accept() on the server socket. An alternative would be to put the server socket in asynchronous mode, then just sit in a loop in the main program doing pause() and handling new connection requests and client requests in the signal handler.
Note that your signal handler will be called any time there is a SIGIO signal, so it doesn't differentiate among the different client connections that might have generated the signal. You will need to figure out which one (or ones) caused the interrupt and handle those connections. You can do this with a select() inside the signal handler.
Just like with the previous program where you implemented child processes to handle the client connections, this program doesn't appear to be saving any work over the version that just used select() in the main loop. This is true; you still need to do the select(), you are just doing it in a signal handler instead of the main loop. Once again, the benefit is that when you aren't in the signal handler responding to an I/O event, the program can be doing other things instead of waiting for something to happen on a socket.
The requirements for this program are thus the following:
There is not a lot of design work to be done here, but you should plan how you will implement the signal handler, what you want to do with the main server socket, and how you will handle the processing of client requests and how you will do that from the signal handler.
You should continue to refine the library of socket functions - for instance, you might add routines to the server code that allow you to set a socket for asynchronous operation, and to install a signal handler.
You should include the following: