CSE 461: Introduction to Computer Communication Networks, Autumn 2012
  CSE Home   About Us   Search   Contact Info 
Home
Overview
Course email
Anonymous feedback
View feedback
Course wiki
Home Virtual Machines
Homework Turnin
Class GoPost Forum
Gradebook
Schedule
Hw/Project List
   

Project 1: Project Source Setup


Overview

All of the project code you write this quarter must operate inside the infrastructure we're distributing as the project 1 base code. This page gives an overview of that infrastructure. Armed with that overview, the code you see, which inevitably contains a lot of details, should be manageable.

The project infrastructure uses a dynamic loading scheme to assemble the set of classes that will loaded together into a JVM for execution. The figure immediately below gives a static view of this process. (This picture shows the console (desktop) execution. On Android, it's identical, except that ConsoleStart is replaced by AndroidStart.)

Execution starts in the main() of ConsoleStart. ConsoleStart statically references NetBase, so initially these two classes are loaded in the JVM. ConsoleStart provides the mechanism required for the user to pick a configuration file. Configuration files contain arguments to programs that run in the JVM. For instance, the configuration file may list the port that the EchoService should use. Among other things, by having distinct configuration files, listing distinct ports, you can run more than one JVM on a single machine (e.g., one playing the role of the client and one the server).

ConsoleStart hands the chosen configuration file to NetBase. Among the information in the configuration file are lists of names of Java classes for which we want an object created in the JVM. NetBase reads these lists of classes and creates a single instance of each. It then transfers control to a specially designated "shell application." Here's the picture of the JVM at this point.

The shell application prints a prompt listing all loaded applications and asking the user which one to run. When the user chooses, the shell transfers control to the run() method of the chosen application.

In this infrastructure, the ping and dataxfer clients you write are applications. (Their code should go in the ConsoleApps Eclipse project, in package edu.uw.cs.cse461.ConsoleApps.) To be loaded as applications, they must implement the NetLoadableConsoleAppInterface interface. That requires implementing a constructor that takes no arguments, a run() method that is invoked when the user requests execution of your application, and a shutdown() method called when the entire JVM is coming down.

In this infrastructure, the dataxfer service you write is a service. (It's code should go in the Eclipse Net project, in package edu.uw.cs.cse461.Net.Base.) It must implement the NetLoadableServiceInterface. During construction it creates UDP and TCP sockets. For each socket, it creates a thread. The sits in a loop waiting for a packet to arrive (UDP) or a connection to be made (TCP). When that happens, the thread sends the required amount of data back to the client, then waits for another incoming packet or connection. A timeout must be set so that the thread will occasionally wake up even if there is no incoming packet connection. That allows the thread to check whether the entire application is trying to terminate. (If so, your service's shutdown() method will have been called, and you can have set a flag in the object that the threads can check.)

During execution, any component can access the configuration file selected when the infrastructure was brought up, and extract from it parameter values that affect that components behavior. The configuration file is represented in memory by a ConfigManager object (found in Eclipse project util). A handle to that object is available as NetBase.theNetbase().config().

Coding: Interfaces

In many cases, the infrastructure uses Java interfaces as a form of documentation. The idea is to have a short file that shows the constraints imposed by the infrastructure - something much shorter than the full source file, which is cluttered with implementation and comments. An interface file for a component you implement shows what promises your component must fulfill -- what the rest of the infrastructure might be relying on. An interface file for a component of the infrastructure you might need to use shows the methods we think you should be interested in, and doesn't show ones we think you shouldn't be interested in. (Method attributes related to Java's protection scheme (public, private, and the like) are unreliable guides to what we expect you to be able to use. A method may be public to ease implementation of the infrastructure itself without that being a sign that we are inviting you to invoke it.)

We followed a convention where interface files have the string Interface in their file name.

Coding: Taking Measurements

The infrastructure implements a class intended to make it easy to run repeated experiements and aggregate sampling information from them. The implementation is in file SampledStatistic.java in Eclipse package util. Because the classes it uses are static, there is no interface file for it, but here is a brief description of how to use it.

The main classes you deal with are ElapsedTime and TransferRate. Each manages a dynamically created set of counters. Counters are identified by string names you make up. A new counter is created when a new name is seen. ElapsedTime counters measure time intervals. TransferRate counters measure transfer rates, which also involves measuring time intervals. Counters have start and stop methods that demarcate the time interval.

Here's an overview of how to use ElapsedTime. TransferRate is nearly identical, except that you have to provide the amount of data transferred on the stop event.


  ElapsedTime.clear();  // destroy all existing ElapsedTime counters
  for (...) {
    ElapsedTime.start("foo");  // create a foo counter, if necessary
    ...
    ElapsedTime.start("bar");  // create the bar counter, if necessary
    ...
    ElapsedTime.stop("bar");   // take a new sample - the time since start("bar")
    ..
    ElapsedTime.stop("foo");   // new foo sample
  }
  System.out.println(ElapsedTime.get("bar").mean());  // print mean of bar counter
Each start of a counter must be terminated with either a stop or an abort call before another start can be performed. (abort records that a failed experiment occurred, but doesn't use the sample in estimating, for instance, the mean.) Other information is available besides just the mean; look at the SampleSet class. There is no requirement that start and stop of distinct counters must nest; the two stop calls above could be reversed, for instance.

Running: The Config File

You must run a client and a server. To contact the server, the client must know what ports it is using. The easiest way to communicate that is to use the configuration files: the server reads the information in it to determine where it should be listening, and the client reads the same information to determine to where it should send. For the dataxfer application, the distributed config file does this:
PropertyValue
dataxfer.server.ip The "IP address" of the machine on which your server instance is running. Because this value is passed through some generous Java interfaces, you can specify either a hostname (e.g., attu1.cs.washington.edu) or an IP address (e.g., 127,208.1.136).

Note: The name attu.cs.washington.edu means any one of four machines, named attu1 through attu4. You should use only the four specific names, to make sure your client is contacting the right machine when trying to locate your server.

Note: You don't have to debug using attu. You can run both the client and server on your development machine while debugging.

dataxferraw.server.baseport The lowest of the four consecutive port numbers used by the server.
net.socket.timeout The number of milliseconds for a thread to wait for data to arrive on a socket before timing out.
net.serversocket.timeout The number of milliseconds for a thread to wait for a connection on a server socket before timing out.
The configuration file also contains properties that apply to the echo server.

Note: The configuration file also contains values intended for later projects (e.g., the echoRPC.xxx properties are for the RPC project).

Note: A full list of configuration file fields is here.

Running: Debug Printing

Eclipse provides an interactive debugger that works well for both console and Android execution (including setting breakpoints and the like in code running on a physical phone). Despite that, you might find it useful to print some debugging/logging information.

The infrastructure supports this via the Log class, which provides methods with names like e(), w(), and d() to print messages at error, warning, and debug levels, respectively. (For instance, Log.e(TAG, "some error occurred"); prints a message at the error level.) This facility works both for console and Android compiles, so you can safely use it in any code you write. It is modeled on the native Android implementation; look at it's documentation for more details.

The config file contains two properties that control Log printing When running in console mode. Property debug.enable is set to 0 to turn off printing entirely, and to 1 to allow printing. Property debug.level is set to a value between 2 (meaning verbose level) and 6 (meaning error level). Printing at levels lower than debug.level is suppressed.

Running: Moving Code to a Remote Machine

When you want to run over the network, you'll need to move your code to some remote machine. The easiest way to do this is to export the code as a jar. The easiest way to do that is to right-click on the ConsoleApps project, then Export..., expand the Java entry and select Runnable JAR file, then Next. For Launch Configuration, choose ConsoleStart. Choose some directory into which the jar should be written for the Export destination, make the name of the file ConsoleApps.jar, and hit Finish.

Now copy ConsoleApps.jar to the remote machine. Put it in a directory that also contains a single configuration file (whose name ends with config.ini), and invoke it with:

java -jar ConsoleApps.jar -d .
(The -H switch will cause a help message to be printed, listing other command line options.)

Computer Science & Engineering
University of Washington
Box 352350
Seattle, WA  98195-2350
(206) 543-1695 voice, (206) 543-2969 FAX
[comments to zahorjan at cs.washington.edu]