File Server/Client Assignment

Due Date:
November 28, 1995
Deliverables:
When the project is complete, send me an email telling the path to the project directory, which is to be empty except for the RCS subdirectory. You may use SCCS instead of RCS, but RCS is preferred. Typing make in the project directory is to cause two programs, a client and a server, to be built. Then, typing make install is to cause the executable files to be moved to ~/bin and the man pages for the two programs to be moved to ~/man/man1. After make install the project directory must be empty again. The make commands must require no interactions with the user, even if repeated again.

If you want to leave a message for me that doesn't belong in the man pages or your code documentation, you may leave a text file in the project directory named README, but a README file is neither required nor expected for this assignment.

Requirements:
In addition to the information given here, be sure to consult the Grading Form for this assignment, which includes additional information about the requirements for this project.

Project Description

One program you are to write is an Internet server daemon which is to process file transfer requests from remote clients. The server daemon is patterned after the Unix ftpd(8) daemon, which implements the protocol defined by the Internet standard, RFC-959. Your server, however will implement a simpler protocol than the one used by ftpd. The other program is an ftp client that interacts with your server to allow users to transfer files between the server's and client's host machines. Do not name your programs ftpd and ftp because those names should only be used by programs that implement the protocol specified in RFC-959.

Note: Feel free to get a copy of RFC-959 to look at, but please do not print it out in the lab. It is very long, you do not need it to do this project. Save a tree and save our printer!

The Protocol

The protocol your client and server are to follow consists of an exchange of requests from the client to the server and replies from the server to the client.

Each request consists of a text line that begins with a keyword, any parameters needed by that keyword, and ends with the ASCII sequence <cr><lf>. No request will be more than 128 characters long, including the termination characters, but one type of request (STOR, see below) is followed by a stream of bytes (the contents of a file) that the server reads without interpreting (it writes them to a file in its current working directory).

Each reply consists of a three-digit string of decimal characters followed by an explanatory phrase of text terminated by <cr><lf>. The decimal string is designed to be interpreted by your client, and the text phrase is designed to be read by the user. No reply will be more than 128 characters long, but some replies are followed by some number of bytes that the client reads and then writes either to a file or to the user's screen depending on the type of request that generated the reply.

The request keywords and their parameters are as follows:

PWD
The client requests the server to return a string telling the current working directory on the server's host.
CWD <pathname>
The client requests the server to change its current working directory to the <pathname> specified in the command, which is given relative to the server's current working directory.
DIR
The client requests the server to send a reply containing a listing of the file names and sizes of all files in its current working directory.
RETR <filename>
The client requests the server to send a reply specifying the number of bytes in the named file, followed immediately by the contents of the file. The client writes the file into its own current working directory.
STOR <filename> <size>
The client requests the sever to store the named file, of the specified size, in the server's current working directory. This message is always exactly 56 bytes long, which allows for up to 32 bytes for the name of the file and up to 16 bytes for the size. Immediately after this message, the client writes the contents of the file to the server, which writes the file into its own current working directory.

The server uses the following reply codes to send messages to its clients:

200 OK
This code is used to indicate successful completion of a request that needs no other information. It is used following successful processing of CWD and STOR commands.
212 <size>
This code is the reply to a DIR, PWD, or RETR request, and specifies how many bytes the server is about to transmit. It is always exactly 23 bytes long, which allows for a 16 digit <size> parameter. Immediately after the 23 byte message, the server sends <size> bytes of information, which the client processes in a manner that depends on what type of request it made.
500 Command Unrecognized
A message from the client did not begin with one of the keywords that the server recognizes.
501 Invalid Parameter
A STOR, RETR, or CWD request could not be processed because of the value of a parameter.
502 Command Not Implemented
As you develop your programs in a sequence of steps, your client might make a request that you haven't implemented yet in your server, and this should be the server's reply.

The User Interface

The client program accepts the following commands from the user:
pwd
This command causes the client to send a PWD request to the server and to display the server's current working directory.
ls
This command causes the client to send a DIR request to the server and to display the directory listing that the server returns.
cd <directory>
This command causes the client to send a CWD request to the server.
get <filename>
This command causes the client to send a RETR request to the server and to store the retrieved file in the client's current working directory. The client displays the number of bytes in the file, and some sort of progress indicator as the file is received. A satisfactory progress indicator would be to show the digits "9 8 7 ... " one at a time each time 10% of the file is received.
put <filename>
This command causes the client to send a STOR request to the server, followed by the contents of the named file. This command also displays the number of bytes to be transferred and a progress indicator during transfer.
exit
This command causes the client to close its connection with the server and to exit.

Development Steps

The project is to be done as a sequence of steps, each of which is to correspond to an RCS major version number. All the files needed to make version 1 of the program must have version numbers in the form "1.x" (where x can be any number greater than zero); all the files needed to make version 2 of the program must have version numbers in the form "2.x" and so on.
Version 1
Create client and server programs that connect with each other using the default port number assigned to you, and program both to accept an alternate port number from the command line. Your default port number is the last four digits of your ID#. (If the last four digits of your ID# are 0403 use 1413 instead.) Select alternate port numbers from your assigned number plus a number between 1 and 10.

The server is to be a concurrent server which forks a process for each client connection. The child processes are to execute a function which must be defined in a separate source file from the server parent process.

For this version, the client and server do not write or read anything over their socket connection.

Make sure the client program terminates normally if the user enters an exit command. Make sure you can connect to the server repeatedly with your client. Make sure you can connect to the server several times concurrently with your client. Make sure the server leaves no zombie (defunct) processes.

Version 2
For this version, implement the user commands pwd and cd. The server can handle PWD and CWD requests using the getcwd(3) and chdir(2) calls. The server should always be able to respond to PWD successfully, but chdir(2) may fail for various reasons, and the client and server must handle this situation properly.
Version 3
Implement the ls command. You can use the system(3) function to run ls(1) with output redirected to a file. The trick is that the name of the file must be unique across all concurrent clients. A process can use getpid(2) to generate unique file names. The /tmp directory is available for temporary files, so a temporary file might be in the form /tmp/<pid>, where <pid> is the decimal character representation of the process id returned by getpid(2). Use the fstat(2) call to determine the size of the temporary file in order to construct the 212 <size> reply message. The server deletes the listing file after it has sent it to the client.
Version 4
Implement the get and put commands. Once you have completed Version 3, there should be no new programming techniques involved in implementing these commands.

When you test Version 4, be sure you have the client and server using different working directories during file transfers or you are likely to get unpleasant results.



Christopher Vickery
Queens College of CUNY