Assignment #4

Due: December 4 before 16:00
To be done in groups of 2 or 3 students.


Grading


Change Log

December 2

November 25

November 24


Introduction

This assignment will introduce you to network communications and client-server architectures. You will first perform a simple experiment to gain some familiarity with network programming, and then move on to the design of a simple client-server architecture for distributed music. While this assignment is a group project, you are strongly encouraged to work through the first part individually, so that every member of your group gains some experience with the network system calls before continuing.

You may use the code provided in the document, An Introductory 4.4BSD Interprocess Communication Tutorial as an example. Make sure that you understand how the code works before you start using it.

Part I: Measuring connection setup/teardown overhead

  1. Using /bin/time, run a series of tests on the ECE network to measure the overhead of setting up and tearing down a stream connection between two hosts. Hint: compare the time required to send a message from one host to another using a SOCK_STREAM socket to the time needed when using a SOCK_DGRAM socket. Because the measured times may be very small, your test programs should repeat the process -- of opening a socket, making a connection (in the case of SOCK_STREAM), sending the message, and closing the socket -- a number of times to ensure accurate values. With reference to your measurements, why does the stream connection program take so long if the CPU usage is similar to that of the datagram program?
  2. Once a stream connection has been established between two hosts, what is the minimum turnaround time for host A to send data to host B and receive a reply?
  3. TCP ensures that you cannot send data faster than the receiver is capable of receiving it. Prove this to yourself by writing a test program for each of these transport layer protocols. A simple test program could send large blocks of data from host A to host B, in which every byte had the value equal to the count of how blocks had been transmitted (e.g. 0x01 for the first block, 0x02 for the second, and so on). What happens when the transmitter sends data as quickly as possible under UDP? How can you prevent this?

Part II: The distributed piano

Your team must now design and implement a client-server system that allows multiple clients to play music on a server machine. A library to generate the musical tones will be made available shortly. The server should, as a minimum, provide the following services to clients:

Command Arguments Description Server response
BeginSession [private] Initiates a music session with the server. If the optional, private argument is supplied, and no other client is already connected, the server will not allow other clients to join. This command must preceed any other commands to the server. Otherwise, the server will respond with ERR_NOSESSION. OK on success, ERR_PRIVATE if another client has invoked a private session, ERR_OTHERCLIENT if private is requested but another client is already connected.
EndSession   Terminates a music session between the client and server. This does not affect other connected clients. OK
StartNote note Instructs the server to start playing the musical note, note. Until further notice, a note is specified simply as a single character, in the range of A through G. The server will continue sounding that note until a StopNote command is received. OK
StopNote note Instructs the server to stop playing the musical note, note. OK on success, ERR_NOTPLAYING if the note is not currently being played on behalf of the client issuing the command.
All messages are sent as ordinary, null character ('\0') terminated, ASCII strings with a single space between the command and each subsequent argument, if any are supplied. For testing purposes, your server must display all of the client messages and its responses to them on stderr.

In order to earn full marks, your server must poll all the clients (both those with active connections as well as those just initiating a session) every note-generating cycle. You will likely want to play with the timing in order to determine an ideal timeout period but the basic idea is to do the following:

while (1) {
	/* clear the read file descriptor set */
	FD_ZERO (&r);

	/* add the main server socket to check for connecting clients */
	FD_SET (main_sock, &r);	

	/* also find highest numbered socket for select() call */
	max_sock = main_sock;

	for (i = 0; i < num_active_clients; i++) {

		/* add the sockets associated with each active client */
		FD_SET (client[i].sock, &r);

		/* check if this client's socket number is higher than max */
        	if (client[i].sock > max_sock)
                	max_sock = client[i].sock;
	}

	/* set a timeout of 100 msec */
	timeout.tv_sec = 0;
	timeout.tv_usec = 100000;

	/* now check all clients for commands */
	while (select (max_sock + 1, &r, NULL, NULL, &timeout)) {
		if (FD_ISSET (main_sock, &r)) {
			/* accept the connection from this new client */
		}

		for (i = 0; i < num_active_clients; i++) {
			if (FD_ISSET (client[i].sock, &r)) {
				/* read the command from this client */
			}
		}
	}

	/* if we make it here, that means select timed out */

	MakeTheSounds();
}

Your clients will work as if they are (strange) musical keyboards. Note that the sounds generated by the music library are simple sine waves and are not intended to reproduce the sounds of a real piano. Do not be alarmed when combinations of various notes sound like hell :-) The following code segment demonstrates how you can set your terminal to return individual keystrokes without the need to issue a carriage return. It is up to your team to decide the best mechanism for indicating the end of a note (for example, you may choose to press the same key twice or use the SHIFT key in combination with the note key to stop the note). Bonus marks will be offered if you make use of the functionality supported by the X library or the Sun /dev/kbd to detect down-key and up-key events to drive the client (thereby creating a more natural piano playing mechanism).

Two lines (in red) have been added to account for termio differences on Solaris vs. SunOS. You need to set the VMIN and VTIME to zero to ensure that each keystroke is returned immediately without buffering.

#include <stdio.h>
#include <unistd.h>
#include <termios.h>

main () {
	char s[1];
	fd_set r;
	struct termios term;

	tcgetattr(STDIN_FILENO, &term);
	term.c_lflag &= ~ICANON;

	term.c_cc[VMIN] = 0;
	term.c_cc[VTIME] = 0;                    

	tcsetattr(STDIN_FILENO, TCSANOW, &term);

	while (1) {
		FD_ZERO (&r);
		FD_SET (STDIN_FILENO, &r);
		select (1, &r, NULL, NULL, NULL);
		if (FD_ISSET(fileno(stdin), &r)) {
			read (STDIN_FILENO, s, 1);
			printf (" - %d\n", s[0]);
		}
	}
}

Testing

A sample test session should include multiple clients and make use of all the functions implemented by your client-server architecture. Specifically, you must be able to generate multi-note sounds from several clients.

Since the marker will not have luxury of listening to your test results, you must provide a transcript of sample server output with your report. The simplest way to save such ouptut is to redirect the appropriate stream to a file, using the '>' (for stdout) or '>&' (for stderr) redirection operators.

Frequency Guide

The following frequencies are a fairly good approximation to the middle octave notes you may wish to use:
Note Frequency
A 440
B 494
C 554
D 587
E 659
F 740
G 831

Consecutive notes within an octave form a geometric series based on the 12th root of 2. In other words, the next note (B flat) after middle A has a frequency of 440 * 2^(1/12).

Submitting your assignment

Each group must submit a single hardcopy consisting of the following:

Note that you do not need to supply your program(s) for part I in electronic form.

In addition to the hardcopy submission, one member from your group must provide an electronic version of your assignment in UNIX tar(8) format, encoded with uuencode(1). The electronic submission will be compiled and tested on one of the systems in the ECE undergraduate lab. The electronic submission must contain:

by sending an email message to the instructor.

Your message must be sent by December 4, 16:00. Assignments will not be considered complete if they have not been submitted both in hardcopy and electronically or if the two versions of the source code differ. Incomplete submissions will not be marked. The hardcopy and electronic versions may be submitted at different times within the assigned deadline.

In order to allow for automatic processing, your submission message must be formatted as specified in the following paragraphs. An unproperly formatted message will be automatically bounced back to the sender and the submission will not be considered complete. You may then correct the errors and resubmit. However, you may not resubmit after a properly formatted message has been accepted: please make sure that your files contain exactly what you wish to submit.

The "Subject:" field of your email message must have the following format: 427-A4-YOUR_STUDENT_ID, with the digits of your student ID number in place of YOUR_STUDENT_ID; do not write anything else in the subject; do not write anything in the message other than the tar file.

The tar file must create, when opened, a directory named with the submitter's student ID, containing all the source files (there may be subdirectories, if needed) and the Makefile as described above. An optional file named README may be included, containing instructions for the correct compilation and use of the client and server programs. Do not include any non-text files (e.g. compiled executables, relocatable objects), since they may be handled improperly by the email software, causing corruption of the entire tar file. Make sure that all files are in UNIX text format (lines terminated by a line-feed character, ASCII 10): use a converter if you edit them on a PC under MS-DOS/Windows.

An example sequence of UNIX shell commands that creates and sends a tar file as specified follows [comments in square brackets]:

[Create the source directory for student with id 952334.]
   % mkdir ./952334

[Copy all the sources in it.]
   % cp foo.c bar.c baz.c flop.c README ./952334

[Create the tar file with the directory content.]
   % tar cvf 427-A4-952334.tar ./952334

[Uuencode the tar file]
   % uuencode 427-A4-952334.tar 427-A4-952334.tar > 427-A4-952334.tar.uu

[Send it with the proper subject field.]
   % mail -s "427-A4-952334"  < 427-A3-952334.tar.uu

If the submission is correct, you will receive an automatic acknowledgement in reply. Otherwise, the message will be refused, and an explanatory error message will be sent to you.