CSE 124
2017 October 12: Homework 2: Sending and receiving data

Resubmission Deadline

Nov 03, 5pm

Due date

Oct 20, 5pm

Overview

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.

Description

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.

Protocol

Download

To download a file, the client connects to the server, issues a RETR command and provides the filename. The <CRLF> delimiter signifies the end of the RETR command.

Upload

To upload a file, the client connects to the server, issues a STOR command and provides the filename. The <CRLF> delimiter 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:

The client

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

The server

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

Misc

File Check

To check whether your client/server are working correctly, you can use the 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

Type man diff for more information.

Thought questions

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.

sendfile()

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.

Evaluation

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 12 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).

GitHub invitation

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:

https://classroom.github.com/a/9haMEiar