Nov 03, 5pm
Oct 20, 5pm
In this exercise, you’re going to implement a very simple, and VERY insecure file transfer service. It supports two commands, RETR (which retrieves a file from the server and downloads it to the client), and STOR (which uploads a file from the client to the server). All files that are retrieved from the server, and all files stored by the clients, are kept in a single directory that is provided to your program as a command-line option. There are no subdirectories. You do not need to support listing files, renaming files, or other operations that a real networked file program would have to support.
Your server will open a listening socket and wait for an incoming request. When a request arrives, the client will issue a single command, and then close the connection. Likewise, when the server is finished handling an incoming command, it closes the socket and waits for the next client.
You do not have to implement a concurrent/parallel server–it is OK to simply handle one incoming client at a time. Also, you can assume that any files to download already exist on the server, that the permissions are all correct, and that the client doesn’t ask for non-existent files. We won’t test corner cases or invalid input–just well formed requests.
To download a file, the client connects to the server, issues
RETR command and provides the filename. The
signifies the end of the
To upload a file, the client connects to the server, issues
STOR command and provides the filename. The
signifies the end of the
STOR command. After the client closes the
connection, the server writes out the file.
Client and server programs
The starter code includes a basic build environment for building the server and the client. In general, they are invoked as follows:
Usage: ./client server server-port [retr|stor] filename
- server: The ip address or hostname of the server
- server-port: The port the server is listening on
- [retr|stor]: indicates whether you want to upload or download a file
- filename: if uploading, the name of the file you want to upload (you can assume that we will pass in an absolute path to the filename–do not use a relative path or assume the file is in the current directory). If downloading, the name of the file you want to download. Note that the server doesn’t support subdirectories, so if you download a file you just give it the name of the file (no path). When downloading, the client should store the file in the current working directory.
You do not have to handle error conditions such as trying to download a file that doesn’t exist on the server, or trying to upload a file that doesn’t exist on the client
Here are some examples:
$ ./client 127.0.0.1 8080 stor /tmp/myfile.txt $ ./client 127.0.0.1 8080 stor /home/users/turing/sample-file.dat $ ./client 127.0.0.1 8080 retr myfile.txt $ ./client 127.0.0.1 8080 retr sample-file.dat
Usage: ./server server-port storage_directory
- server-port: the port to listen on
- storage_directory: an absolute path to a directory that should store files uploaded from the client
Here are some examples:
$ ./server 8080 /home/users/turing/stordir $ ./server 8080 /tmp
To check whether your client/server are working correctly, you can
diff command in linux. Simply upload a file, then download
that file, and compare the two. As an example:
$ cd /tmp tmp $ client localhost 8080 stor /home/users/aturing/sample-file.dat tmp $ client localhost 8080 retr sample-file.dat tmp $ diff /tmp/sample-file.dat /home/users/aturing/sample-file.dat
man diff for more information.
This simple implementation of a file transfer service uses an implicit signal that the transfer of the file being uploaded/downloaded has ended, namely the close of the TCP connection. Your web server project will use an explicit signal. What is that signal? What does having an explicit signal allow that this implicit signal doesn’t? You don’t have to answer these questions as part of the homework, but think about them.
You should take a look at the
sendfile(2) system call, which can make
implementing these kinds of file transfer services much easier.
In particular, it allows you to instruct the operation system kernel
to copy the contents of an open file handle to an open client socket.
We will run your server, pointing the upload/download directory to one with a set of pre-loaded files. We’ll run 10 different tests, 5 upload and 5 download, and each will be worth 1⁄2 point. The files we’ll test against will include a mixture of text and binary data, and a mixture of sizes (small, medium, and large).
You can modify these files as long as we can type “make” on the ieng6 servers and have it build correctly. You can use C or C++ (up to and including version C++11). You are free to use man pages, standard libraries installed on the ieng6 servers, any code we talk about in class, and any code from the assigned readings/texts. For anything else, please ask first!
To fork the starter code, use this GitHub.com classroom invitation: