CENG 320 Lab 3 Writeup
I may not have had enough time to go through all of this in class.
Part I – exercises 1 and 3
The server program is based on echoCommandServer2. For readablity I’ve stripped out all other functionality – the only command recognized is download. The only comands recognized by the client are download filename and bye.
The client uses chdir to switch to a directory downloads. After each file transfer it switches back to the parent directory. This it uses system(“ls -l downloads”) to show the current content of the file.
To detect end of file the server closes the connection. The client also closes the connection and reconnects. To make this easier the code to connect to the server is put in a function – same idea as the C++ code in Lab 1.
Part 1 – exercise 2
The only parts of the program that needed to be protected using pthread_mutex_lock were the increment and decrement of a connection counter. The call to fork was changed to pthread_create which invoked HandleTCPClient which was altered to return void *. Searching for the word pthread will reveal all the sections where the code was changed.
Testing was done by compiling and running the program on munro and multiple clients on apollo using telnet. The increment and decrement worked fine as long as there was an orderly exit using the bye command.
In a window was closed to end a connection the count was not decremented. This wasn’t a requirement but it is something worth thinking about. One answer to this would be to add a signal handler for SIGHUP and any other signal that would decrement the counter properly. However this wouldn’t handle the case of SIGKILL.
Part II – Services
The modified and created files can be found on the course web page.
Q1 is verified by your partner.
Q2: To create the daytime service, copy echo.socket to daytime.socket and echo@.service to daytime@.service. In the daytime.socket change ListenStream=13since daytime has a standard port # of 13 (hopefully you checked /etc/services for this) and change the description [Unit} section of both files. In the .service file change ExecStart=-/bin/cat -n to ExecStart=-/bin/date
Then use systemctl to start and enable the service and then test it using telnet.
Q3: qotd is run on port #17. Note the requirement to move the cows directory to your ceng320 directory and set up COWPATH in the script file. The script can be testing in the command line and then should be tested as a service.
Part III
UDPClient1.c and UDPServer2.c are both stub programs that recognize but do not process the relevant commands for each side. UDPClient1 which is based on Beej 6.3 and/or my listener2.c UDP client program recognizes the commands fileSize, send *, check, join and I added bye (not req’d). In UDPClient2.c I added a command bash (not req’d) to temporarily go into a bash sub shell in order to examine files. A 3rd terminal window would do just as well – I thought it would make things easier when demonstrating in class.
UDPServer1.c recognizes the commands fileSize, send *, send nnn and bye. It is based on Beej 6.2 and/or my talker2.c. You could have started from either program as an example.
UDPClient2.c and UDPServer2.c implement these commands. Neither program is robust in the sense that improper use of commands such as requests for files that don’t exist, joins for files where packets have yet to be downloaded, file names longer than 100 characters and so forth may cause it to crash. That’s within the parameters of the assignment.
Both programs determine the current file name using the fileSize command. The server responds by sending the file size in bytes followed by the # of packets, formatted in plain text. The formula used to calculate the # of packets by adding 79 (buffer size -1) does look a bit odd. A better approach might have been to convert the values to double and used the ceil(double) function. If your program doesn’t give special handling to the last record and you don’t notice I’ll deduct a mark. If your calculation is off in special cases I’ll deduct ¼ .
UDPClient2 determines that send * has finished sending data by using a timeout delay of 2 seconds. Other approaches might be sending a different sized record to signify no more records or a record with a packet # of -1.
UDPClient2 generates multiple send nnn commands when you invoke the check command. There is nothing to prevent you from issuing a single send nnn command yourself – the server doesn’t care. A side effect of the program is that if you issue a check command before issuing a send * command, all the packets will be downloaded individually.
UDPClient2.c uses the system function call to clean out old packets from the temp directory. The main program creates tempthe first time it is used and doesn’t care if it’s already there. This means if you try to run the program in a different directory or account you don’t have to worry about manually creating it. The use of temp also means you don’t have to worry about your program killing an original file or cluttering up your directory if you test both client and server on the same machine. The use of rm packet* means you don’t have to worry about accidentally erasing all of your files.
The join command uses the triadic operator to determine whether or not one is dealing with the last packet. If it is then the # of bytes written to the file is the file size in bytes % 80. Otherwise a file of size 840 bytes would be padded to a size of 880 bytes.
In a more realistic environment packets might arrive out of order and the program might be waiting for the response to a fileSize when a file packet is sent instead.
UDPServer2 opens the file and closes it once before and after send * command. It opens and closes it before each send nnn command which is slightly inefficient but the code is easier to understand than keeping it open until all records are sent.
I left a number of debugging/information statements in both programs to reflect what what happening. Thought not required this approach can be very helpful and is known as defensive programming.
Note on testing:
I issued the following commands
fileSize blorkDemo.c
send *
check
join
Checked file size and contents by looking at it. I had to fix one problem where send nnn got stuck sending the last record. I did initial testing on one machine, I was able to use theUnix diff command to show there were no differences between files. I did check several other files including a compiled file (hello) and a zero length file. After changing the permissions on the compiled file it ran.