----------------------- Lab #02 for CST8165 due September 13, 2006 (*UPDATED*) ----------------------- -Ian! D. Allen - idallen@idallen.ca Remember - knowing how to find out an answer is more important than memorizing the answer. Learn to fish! RTFM! (Read The Fine Manual) Global weight: 2% of your total mark this term. Due date: At the start of your lab period on Wednesday September 13. A partial demo at lab start is worth bonus marks. The on-line deliverables for this exercise are to be submitted on-line in the Linux Lab T127 using the "cstsubmit" method described in the exercise description, below. No paper; no email; no FTP. Late-submission date: I will accept without penalty exercises that are submitted late but before noon Friday September 15, 2006. After that late-submission date, the exercise is worth zero marks. Exercises submitted by the *due date* will be marked on-line and your marks will be sent to you by email after the late-submission date. Demos available to be seen at the start of your lab period will be considered for bonus marks. See the marking scheme below. Exercise Synopsis: Upgrade your client/server pair. Implement a multi-client server using select(). Where to work: Submissions must compile and run cleanly in the T127 Linux Lab, though you are free to develop and work on them anywhere you like. Recall that most any program or C function has a Unix/Linux manual page: RTFM Code submitted without your added useful comments will not be marked. Code Quality and Portability ---------------------------- A. Your C programs must compile without warnings (gcc -Wall must be silent). B. Your code must work on any machine, no matter what its byte ordering. (Always convert bytes between host and network byte order.) C. You must include useful comment blocks ahead of the code you write or modify. Code submitted without your added useful comments will not be marked. Coding client/server -------------------- This lab works with sample code copied (with credit) from here: http://beej.us/guide/bgnet/output/htmlsingle/bgnet.html 1) Upgrade your server to handle the case where not all the bytes get written to a socket (the kernel only sends some of the data, not all of it). You might implement a function similar to sendall() in "6.3. Handling Partial send()s" here: http://beej.us/guide/bgnet/output/htmlsingle/bgnet.html#sendall C Style: Functions that are not used outside the source file must be declared "static". This prevents global name space pollution, misuse by other modules, and documents to the reader that this function is local to this file. 2) Rewrite your Perl client in C language, using fork() and two looping processes to simultaneously handle the keyboard and the socket. I recommend extending a sample single-process client, e.g. start with http://www.cs.rpi.edu/courses/sysprog/sockets/client.c (fix the compilation errors; document the code) and add the fork() to create two separate looping processes to handle reading the keyboard and reading the socket. Note: This client.c fails to detect EOF or error on standard input; make sure your own code does not have this flaw. You may choose to get rid of fgets/stdio and use a plain "read" system call to read standard input. Handle EOF or error from the keyboard correctly - use shutdown() to close the socket so that the server sees EOF and closes the client connection. (The shutdown() function was mentioned in the previous lab.) See the notes file eof_handling.txt for details. The client process reading the server socket should exit only when the *server* closes the socket (or on error). The process reading the server socket and the process reading the keyboard are largely independent. The exception to the independence of the two processes is this: If the client process gets an EOF or error reading the server socket, it should kill the client process that is reading the keyboard, on the assumption that if the server has closed the socket, the client won't be able to send any more keyboard input and both processes should exit. 3) Upgrade your client to use the same function you just wrote (above) for the server to send all the bytes down the socket. Oh! Now we have the same code in both the server and the client. Cut out the all-sending function into its own source file "sendall.c" and set up multi-file separate compilation for the client and the server. (The send-all function will be in a file common to both programs.) 4) Build a simple Makefile to ensure that changes to any of the source files cause the respective binary to be recompiled when you type "make". Changes to the common file must cause both programs to recompile. 5) Create a Makefile target named "clean:" that removes all the compiled binary programs and object files. Create a Makefile target named "all:" that rebuilds all your programs. Ensure that "make clean" followed by "make all" rebuilds all your binaries from scratch. 6) Read the section on "6.2. select()--Synchronous I/O Multiplexing" in http://beej.us/guide/bgnet/output/htmlsingle/bgnet.htm Note (RTFM) the functions/macros used to manipulate bit vectors in the select() call: FD_ZERO, FD_SET, FD_ISSET, FD_CLR 7) Copy the small demo from "6.2. select()--Synchronous I/O Multiplexing": http://beej.us/guide/bgnet/output/htmlsingle/bgnet.html#select http://beej.us/guide/bgnet/examples/select.c Instead of saying "A key was pressed", modify the demo program to read one line (up to 256 bytes) from stdin and print the result on the screen before exiting. C Style: You can print exactly 9 bytes from a buffer (no \0 needed) using: printf("%.9s",buf); // print only 9 bytes from buf AND it gets better (more useful in this case): n = read(.... ); ... printf("%.*s",n,buf); // the "*" picks up the current value of "n" This kind of printf can be useful for buffers that don't have \0 in them. 8) Copy the "chat" server from "6.2. select()--Synchronous I/O Multiplexing". http://beej.us/guide/bgnet/output/htmlsingle/bgnet.html#select http://beej.us/guide/bgnet/examples/selectserver.c Compile it and test it using telnet or "nc -v localhost ". 9) Integrate compiling the the chat server into your Makefile. "make clean" and "make all" should work for the chat server. 10) Modify the chat server to take the listening port as a command-line argument, similar to the way your other server works: $ ./chatserver 5000 & 11) Modify the chat server to use your new send-all function on its socket writes. Use the same common source file you used above. Ensure that the Makefile dependencies are updated. 12) Modify the chat server to adjust the value of fdmax downward (if possible) when a client connection terminates. 13) Modify the chat server to announce the arrival of a new client to all the other clients. Include the source IP address (in ASCII dotted-quad format) of the connecting client in the announcement. (See "man inet_ntoa" for a function that will help, and make sure you get your byte ordering correct before you convert.) 14) Modify the chat server to announce the departure (EOF) of a client to all the other clients. Include the source IP address (in ASCII dotted-quad format) of the departing client in the announcement. 15) Modify the chat server to prefix the bytes distributed to all the clients with the IP address of the source of the bytes; so, distributed messages are always prefixed by their source IP number, e.g. 1.2.3.4: hello this message comes from me at this address If you find yourself duplicating code, refactor your source and create a (possibly static) function to handle the duplicate code in one place. Code submitted without your added useful comments will not be marked. In-Lab Demonstrations --------------------- At the start of your lab period, show your instructor your select demo (Step 7) and at least your basic modified chat server (any of Step 13-15) and associated Makefile. Partial demos are worth part marks. Submission and Marking Scheme ----------------------------- Submission Standards (see the previous lab for details): 1. At the top of each and every submitted file, as comments, create an Exterior Assignment Submission label. 2. For material you copy from other sources, credit the author and source. 3. Submit your files for marking as Exercise 02 using the following *single* cstsubmit command line (always submit all files togather): $ ~alleni/bin/cstsubmit 02 \ Makefile client.c server2.c sendall.c select.c selectserver.c A partial demo (see above) at the start of your lab period is worth bonus marks. Code submitted without your added useful comments will not be marked. New marking scheme is out of 80: Makefile source: 10/80 client.c source: 10/80 server2.c source: 10/80 sendall.c source: 10/80 select.c source: 10/80 selectserver.c source: 30/80 Demo seen at lab start: 15 bonus marks