Engineering Computing

PI: Laboratory 3: Systems of Objects; Nodes and Channels

You should read through this entire assignment before you begin.

Preparing for the Lab

1. Experiment with the application.

This week's laboratory project involves a network routing simulation. In the simulation, routers (nodes) send and receive packets (pieces of information) to each other along various routes (channels). The nodes could be computers, for instance, sending and receiving information from each other across the internet. This problem set could be a scaled down (very scaled down) version of a commercially available product. The Codewarrior project is set up such that running the project will start the simulator.

The idea of the simulation is to experiment with various network configurations and empirically determine their behaviors. In other words, play with the application and see what happens. When the GUI pops up, you will see two panels, side by side. The panel on the right, which is currently empty, is where all of the simulations will take place. The panel on the left contains the available GUI elements -- all nodes, in this case. Above both panels are three menus: File, Simulation, and Selection. To use the simulator in the most basic way, you first construct a network and then set it in motion. The necessary steps are described below.

One of the main things you need in a simulator are nodes. In order to add a node to your simulator, select one of the nodes from the panel on the left, then click on the drawing panel to place it somewhere. There are three types of nodes which appear when you first run the program:

  • Generator Node - a source. It generates objects (packets).
  • Default Connecting Node - a connecting node. It receives packets and passes them along.
  • Terminator Node - a sink. It eats packets.
To remove an element, click on it and then select Remove from the Selection menu.

The other crucial element in a simulator are channels. Channels run from one node to another, and are represented by a black line with an arrow, connecting the two nodes. In order to add a channel to your simulator, double click on the first node, then click on the second node. Channels have directions: they go from the node you start with to the node you end with. It is possible to have more than one channel between two nodes (e.g., one in each direction), but this isn't drawn particularly well. To remove a channel, outline the channel's arrow by clicking on it, then select Remove from the Selection menu.

To start objects moving through the demo, select Start from the Simulation menu. You can pause the simulation using Pause. You can dynamically add elements while the simulation is running. You can also temporally disable a node or channel by selecting it and then choosing the Disable command from the Selection menu. To re-enable an element, use Enable. Using the Remove option to physically remove an element from the network while the simulation is running is discouraged; deletion is provided only for creating a new network, not for dynamically changing network behavior.

Experiment with the network for a few minutes. Can you get the channels to fill up? Can you create any other interesting behaviors? Remember that you can disable channels (using the Selection menu) while the simulation is running. You may want to keep a record of your experiments to compare your later results with. (Such a record should include both network topology (how things are connected) and dynamic behavior (what you did, what it did).) You can even save any particularly interesting network configurations using the Save As option under the File menu.

We have provided two types of connecting nodes. The first, and the one you have been using (Default Connecting Node), uses a DefaultNodeBehavior. The other type of connecting node you can load is IntermediateNodeBehavior. To run a node with the IntermediateNodeBehavior, modify the Program Arguments to read: nodenet.IntermediateNodeBehavior

In the GUI elements panel, you will see this fourth type of node. Can you discern any differences between the IntermediateNodeBehavior and the DefaultNodeBehavior? What advantages, if any, does one enjoy over the other?

2. Design your code.

In this lab, you're going to create your own behavior for a Node. You will do this by creating a class that implements NodeBehavior. You may want to look at the code for the NodeBehavior interface now.

Your NodeBehavior class will not be a Runnable; instead it will be called by a Node, which is Runnable and has its own Thread. The Node's run method also contains the while(true) loop. (Node also implements the graphical user interface (GUI) for a node.) The heart of Node's run method looks something like this:

InputChannelVector inputChannels;
OutputChannelVector outputChannels;
public void run( ) {
    while( true ) {
        this.nodeBehavior.transmitPacket( this.inputChannels,
                               this.outputChannels );
Since transmitPacket( ) will be called from inside a while( true ) loop, you only have to handle one object at a time.

Note that transmitPacket( ) takes in two arguments. The first argument is an InputChannelVector; the second argument is an OutputChannelVector. Both InputChannelVector and OutputChannelVector are essentially Vectors, except that instead of containing Objects (being a "Vector of Objects"), they contain one or more InputChannels an OutputChannels as appropriate (e.g., InputChannelVector being a "Vector of InputChannels").

In the first argument, each InputChannel in the InputChannelVector has the following method:

    public Object readObject()
        throws ChannelEmptyException, ChannelDisabledException;
You only need to read one packet from one input channel on each time around the interactive control loop, though. Note that a given input channel may be empty or disabled, in which case it will throw an appropriate exception.

The second argument to transmitPacket( ) is an OutputChannelVector. An active non-full output channel would be a good place to put any packet you may have picked up. As a corollary to InputChannel, OutputChannel has

public void writeObject( Object ) 
   throws ChannelFullException, ChannelDisabledException;
But be careful: when an output channel is full, it will throw an exception if you try to write to it. Make sure that you don't drop any packets if this happens, or write packets that don't exist.

The main piece of your job is to implement the transmitPacket( )method of NodeBehavior. This method should take an object off an InputChannel from inputChannels (using readObject()) and feed it to an OutputChannel in outputChannels (using writeObject()). Remember that you may have multiple InputChannels and OutputChannels, and that some of them may be disabled..

There are several ways that you can choose the input and output channels from their respective Vectors. Think of at least two, and record these strategies. The more creative you can be, the more interesting your lab will be. You should design code for at least one of these strategies, and ideally for more than one.

You should be aware that both InputChannelVector and OutputChannelVector contain a method, size(), which returns the size of the Vector; additionally, both contain a method, isEmpty, which returns True if the Vector is empty.

Additionally, InputChannelVector contains three more methods:

  • elementAt( int index ) returns the InputChannel which is at index. Remember that numbering begins with 0.
  • firstElement( ) returns the InputChannel which is the first in the InputChannelVector.
  • lastElement( ) returns the InputChannel which is the last in the InputChannelVector.

OutputChannelVector contains the same three methods listed above, except that each method returns an OutputChannel instead of an InputChannel.

One of the main points of this lab is to observe the effects of different strategies on the behavior of your network as a whole. Is your strategy fair? Does it drop packets? Create them? Do packets cluster in certain parts of your network? Can you come up with a strategy that behaves differently?

Some utilities that you might want to use:

public static int cs101.util.MoreMath.randomInt( int range );
returns an int between 0 and range, inclusive. You can refer to it as MoreMath.randomInt if you include the line import cs101.util.*; at the top of your file.

public static void Thread.sleep( int millis )
    throws InterruptedException;
causes the current Thread to sleep for millis milliseconds. This allows you to put delays in your nodes. Warning: You will have to catch the exception, though you don't necessarily have to do anything with it.

If you have other ideas, design them and then ask us about them.

3. Handle exceptions.

Channels occasionally throw exceptions. You need to be concerned about four of these:
  • ChannelFullException, thrown by a OutputChannel on writeObject().
  • ChannelEmptyException, thrown by a InputChannel on readObject().
  • ChannelDisabledException, thrown by any Channel when its corresponding Channel has been disabled.
Make sure that your code is robust to these exceptions, and does not lose objects.

Building your code.

Your job in lab is to implement one or more node behaviors, to test these behaviors on your own examples, and to exchange example networks with other students in the class. During lab, we will create a shared repository of test networks. Test data development should be pooled, and sharing of test data is encouraged. Discussion of why networks behave as they do is strongly encouraged. Talk to the people next to you to get good ideas for test networks. If you need help loading another student's test network, please ask us to show you how.

Begin the lab by implementing a node behavior. You will need to define a new class, say MyClass. What should you call the file it's defined in? What does it need to extend or implement? What methods does it have? (Remember that the interactive control loop is already defined for you, but it expects to be able to call your transmitPacket() method with two arrays.

The first lines of your file, before your class definition, will need to say:

package nodenet;
Also, you should be sure that your class is public.

Once your code compiles, you should try running it. To run your code, you will need to supply the name of your node behavior class to nodenet. You can do this by supplying the fully-qualified name of your class as the Program Arguments. Remember that the fully-qualified class name includes the package the class is in: nodenet.MyClass. (assuming that MyClass is the name of your class, and also that you've already compiled your class using javac.)

You can now test your code using a network you have saved. It is probably best to use a very simple network first -- if you don't have a simple one saved, you might want to create one now.

Once you have this network running, try some others. See if you can find one that stumps your code. (Try to fix it, or at least to understand why. Can you design another network to stump your code?)

Don't forget to tell the course staff about your networks, so that we can use them, too :)

Writing a class that compiles, runs, and attempts to forward packets is the target exercise for this lab. It need not forward packets perfectly, just make some progress on sane networks.

Post-Lab, AKA What To Turn In

Your completed assignment should include:
  • on the front page, how much out-of-class time (approximately) you've spent on reading, on preparation of the homework, in lab, and on other non-class-time course-related activities (and what). These times should include work from last Wednesday 5pm to this Wednesday at 5pm
  • a brief description of your expectations before coming to lab. (This may be a version of your notes for check-in.)
  • a discussion of how you spent your time in lab.
  • ONE well-documented Java file. If you write more than one java file, pick one to document and turn in.
  • How closely does the following statement describe you:
    I can write a .java file containing a Java class that implements an interface.
    1. I am the master of java class file writing.
    2. I can work it out given a while.
    3. I find the syntax of the class file confusing.
    4. Impl-huh the inter-what?
    5. Java Rules!


Solutions will be availble here at the conclusion of the lab.

Questions, comments, gripes and other communication to
This course is a part of Lynn Andrea Stein's Rethinking CS101 project at the Computers and Cognition Laboratory and the Electrical and Computer Engineering area at Franklin W. Olin College of Engineering. Olin College Logo