Tufts CS 117 (Fall 2024):
Internet-scale Distributed Systems

Tufts CS 117 Programming Assignment
Testing and modifying the datagram ping programs

Goals

Next week we will begin a more ambitious assignment using end-to-end approaches for validating file copying through noisy networks. This assignment is a simple preliminary, to familiarize you with the support code that is provided for you, to uncover logistical problems early, and to give students who did not have CS 112 their first taste of writing distributed code at a low level. Any distributed program can fail in tricky ways, but this assignment is not intended to be difficult. Indeed, for those who don't encounter setup problems, and especially for those who have experience with distributed programming, it may be quite quick and simple to finish.

This assignment is considered part of the larger file copy assignment, so it will be graded along with the final submission for that.

NOTE 1: As CS 112 graduates will quickly realize, the framework provided to you hides a lot of the low-level bit-twiddling and byte swapping needed to keep socket interfaces happy. The focus in our course is more on higher level distributed design concepts, so having the framework should help you get your packets on the wire more easily. Of course, the tradeoff is less fun wrestling with sockets. You are welcome to read the framework source: the header files are in the /comp/117/files/c150Utils directory, and the .cpp source is in the src subdirectory. If any of you miss the experience of socket-level programming, which is definitely fun in its own way, let me know and I'll consider working it into later assignments; I've been debating whether it's something you'll enjoy or whether it would just be rendundant for those who've had 112 and an impediment for those who haven't. Let me know if you have an opinion.

NOTE 2: Earlier offerings of this course were taught as COMP 150-IDS, not CS 117. Much of the framework code you use here was developed for that, so you will see many references to COMP 150, directories named c150Utils, etc.

Overview

In short you will:

Doing this is just a few lines of code once you figure it out, but it should prepare you to implement the more complex packet protocols we'll start on next week.

What to do

There are several basic steps that you will take. The following is to build and test the code:

  1. Make sure your login script sets the COMP117 environment variable to /comp/117. Instructions for doing this are available on the course information page.
  2. Copy the directory /comp/117/files/DatagramSamples to your local space. Retain the DatagramSamples name, so you can eventually do a provide on it. Your command will probably look like:

        cd <Your_Parent_Directory>
        cp -R /comp/117/files/DatagramSamples . <-- note the dot


  3. Read the source for the two sample programs pingclient.cpp and pingserver.cpp to understand how they work. Part of the purpose of this is to learn the COMP 150 networking framework that they use, so you can also explore the header files (and if you like, the .cpp files) for the framework. Detailed knowledge of the framework internals is not required. You just have to know how to use it. The ping code is short and carefully commented to help you learn.
  4. Use make all to build the client and the server. Do all this on the main homework.eecs.tufts.edu server. (Note also that make clean will remove all object code and executables, leaving you more or less with the directory as you installed it. It will not undo any changes you've made to source code.)
  5. Now open two windows on our virtual servers: for consistency, I suggest we all run clients on comp117-01 and servers on comp117-02, but either way should work.
  6. If you've read the code, you should know how to test the client and server together. You will provide a servername (comp117-02) and a short message as two arguments to the client (be sure to quote the second argument if it has spaces in it), and to the server you provide a number, called a nastiness level. For a start, use "0" (zero — without the quotation marks). Start the server first, and then try the client; if you run the client with no server, it will hang waiting for a response — you'll fix that below. The server should echo your message. Read the code to see what it does: it's very short.

Once you've got the unmodified code running, you'll make your own enhanced version of the client. To make these changes, do the following:

So the changes are: send multiple messages from the console instead of one from the command line; retry when message sends aren't answered; always suck up and print any extra messages from the server before going back to read the console; throw an error if the server doesn't answer after 5 tries. You'll see why we're doing the re-read loops when you start playing with different nastiness levels.

In fact, that's the next step:

Testing and preparing to answer questions

Once your code appears to work, please do the following:

The debugging framework

Distributed programs are notoriously hard to debug, and in a class like this, you could spend a lot of your time trying. One tool that makes debugging easier is a logging facility that leaves a trace of every message you send and receive. One of the reasons for giving you the framework, other than to save you from some low level socket programming is to start you off with a useful tracing facility. Note that, once you are running programs with timeouts and on multiple machines, tools like gdb and ddd aren't as useful as in other cases, though by all means use them when you can.

To get a general idea of how the tracing framework is used, read the code in the pingclient and pingserver. Also look at c150debug.h in the utilities directory /comp/117/files/c150Utils (note that the Makefile you're using gets the headers from there). It explains the debugging interfaces. After you run the client and the server, you'll find timestamped trace files called pingclientdebug.txt and pingserverdebug.txt.

Furthermore, note that the c150debug -> enableLogging call (look near the end of the client and server source) lets you choose classes of debugging information to be logged. The header file defines the classes and you can define your own. So, when you have bad bugs, enable more debugging information, when you don't need it, turn it off. The client and server code we give you directs debug output to the log files mentioned above (see the first few lines of function setUpDebugLogging); you can comment out the three lines that do that, and logging will then default to stderr.

Another trick with the logs: let's assume your logs are pingclientdebug.txt and pingserverdebug.txt. Now try this:

   cat pingclientdebug.txt pingserverdebug.txt | sort > mergeddebug.txt

Check out the resulting merged file. Note that the server traffic is indented. That's what the mysterious c150debug->setIndent(" "); call is doing in the server. I suggest you do the same when you want classes of traffic to stand out in merged logs. Note also that the timestamps are carefully arranged to come out in time order when a simple character-based sort is used. WARNING: this trick works often but not always. Why? Our VMs often run on the same physical machine: when they do, their time of day clocks are in perfect sync. In other cases, they can be off a bit, in which case you'll find that the merged logs may not have things in the right order. This is a classic problem in distributed debugging. Even then, the merged logs can be useful, as you can usually figure out what the offset is. One could (and I have on other projects) written code to fix up the timestamps before merging: when you do, causality reappears!

Submitting your work for grading

There is a short HTML q/a form you should fill in and provide with your code. You may, but need not, leave it to us to rebuild your code, but please make sure that:

 make clean         < should delete your pingclient2.o and executable
       --- and ---
 make pingclient2   < should build it

Use the following links to review and download the q/a for this assignment:
Review response form for this assignment - Download response form for this assignment

To keep the submission process simple, put the html q/a form in your DatagramSamples directory, where it will be submitted automatically with the code.

cd <parent-of-your-test-DatagramSamplesDirectory>
provide comp117 ping DatagramSamples 

If you have an explain.txt file to explain a late submission, give that as an additional argument to provide as usual. Please do not put explain.txt files in the code directory, as we may miss them there. So, in that case:

cd <parent-of-your-test-DatagramSamplesDirectory>
provide comp117 ping DatagramSamples explain.txt

Collaboration

For the second part of the assignment we'll work in teams. For this first part, I'd like each student to do their own submission. It's not a lot of work once you understand it (I hope!)

The purpose of this assignment is to bring you up to speed on the framework. You may talk with fellow students or others to help learn the framework and to understand the problem statement. You should write the code yourself. You need not acknowledge general help in understanding the code I've provided to you, but if you're submitting anything that you did not then design and write completely independently, you must acknowledge that. When in doubt, explain the help you received.