CS
555 - Computer Networks
HW5
Spring
2005
Last updated
28-Mar-2005
UPDATES: hw5SourceFiles.zip,
tester
class compiler error fix help1and RMI
fix with SDK1.4 help2
Given March 08, 2005
Due : March 17, 2005 (11:00am) - Extended to March 22, 2005
(11:00am) - Design Specs
March 29
April 5, 2005 (11:00am) - complete
NOTE: I MAY UPDATE IT AS NECESSARY. WHAT I HAVE SO FAR SHOULD BE ENOUGH
FOR YOU TO COMPLETE THE ASSIGNMENT, HOWEVER.
Reliable
Data Transfer Protocol Implementation
A Sliding
Window Data Transfer Protocol
Introduction
This assignment deals with achieving
reliable data transfer over LRD network channels. An LRD channel can lose,
reorder and duplicate messages in transit, subject
to a maximum message lifetime; that is, a message sent into an LRD channel
can be received at zero or more instants within the maximum message lifetime
of its send. You are provided a specification of the data transfer service
and a specification of the LRD network layer service. You are to implement
a protocol that provides the data transfer service using the LRD service.
Your protocol must be based on the sliding window mechanism. You will also
need to implement the AIMD algorithm to adapt your window size. You can
choose the particulars of the design, including message types and their
formats, sequence number space, data block size, retransmission policy,
acknowledgment (cumulative and/or selective) policy, round-trip time estimator,
etc.
Your grade in this assignment is primarily based on your protocol's correctness
, that is, whether it achieves reliable data transfer. Although you could
get by with a very restricted protocol (e.g., window size of 1, a fixed
window size, etc.) in this assignment, such a protocol will not
have good flexibility. So you should develop a sufficiently general
protocol. You have about 3 weeks for this assignment.
Specifically, the assignment consists of two interacting programs, a
Source and a Sink, as shown in figure 1. The Source consists of
three components: SourceTester, SW_Source and NetworkSocket.
The Sink consists of three components: SinkTester, SW_Sink
and NetworkSocket. SW_Source and SW_Sink represent the transport
entities, SourceTester and SinkTester represent their users, and the pair
of NetworkSocket represent the network entities, providing the LRD channels.
You are to implement SW_Source and SW_Sink. We provide the other
entities.
Figure 1
Network Layer Service
Class NetworkSocket
provides the LRD channels to be used by the transport entities to
communicate with each other. Use it instead of the usual sockets (because
in a LAN environment the provided channels display hardly any loss, reordering
or duplication). Import NetworkSocket.java
file to use instead of the provided channels.
A NetworkSocket object is a "wrapper" to a standard socket object.
Incoming packets (i.e., packets received from the Internet) addressed
to the standard socket are immediately passed up to the local transport
entity. Outgoing packets (i.e., packets generated by the local transport
entity) are buffered in a outgoing packet queue, subject to loss, reordering,
duplication and delay before being passed to the underlying standard socket
for sending to the remote socket. The extent of loss, reordering and duplication
depends on probability parameters which can be set on the fly (important
for testing). The delay between sending packets depends on a parameter
that reflects the available bandwidth; this also can be set on the fly
(important for testing).
[Note: In this particular implementation, the LRD errors for a message
are decided when the message enters the socket, that is, when a packet
is sent into NetworkSocket, the packet is either dropped, or inserted
at some position in the outgoing packet queue, or duplicated and the various
copies inserted into various positions in the outgoing queue. Messages
with size bigger than msgMaxSize (defined inside class NetworkSocket)
are discarded without notice.]
Public methods of Class NetworkSocket:
- Constructor NetworkSocket(
int aLocalPort, String remoteDN, int aRemotePort)
Creates the LRD service socket at local site (a corresponding entity
would be created at the remote site). Parameters are as follows: aLocalPort
is the local port number; remoteDN as the name of the remote host; aRemotePort
is the remote port number;
- Method public int send(
byte[] data, int len )
Constructs a network packet containing the data and sends it out on
the outgoing LRD channel. (In the current implementation, the packet
is subjected to loss, reordering and/or duplication, and inserted in
the outgoing packet queue; at some later point the packet(s) is sent
into the Internet.) The network packet is of class NetworkPacket
(analogous to DatagramPacket).
- Method public void receive(DatagramPacket
dp, int timeout) throws IOException, InterruptedIOException
Checks if a network packet has been received from incoming LRD channel.
If a packet is available for reception within timeout value, it passes
the received packet to the caller in parameter dp, which must have a
buffer of max packet size in caller memory space. If no packet is available
for reception within duration timeout, it throws exception
InterruptedException. Upon any other IO error, it throws with
exception IOException; you do not need to exit on this error,
unless it happens frequently.
- Method public
int getMsgMaxSize()
Gets message maximum size. NetworkSocket class discards messages with
size bigger than msg max size without notice.
- Method public void close()
Closes the socket.
Comments:
- The loss, reordering and
duplication probabilities can be varied during execution. You may want
to first fix them at zero for debugging purposes. Given a pair
of peer NetworkSocket objects, the probability and bandwidth parameters
can be different in each object, i.e., different for each direction.
For debugging purposes, you may want to set the errors to zero in one
direction.
The same considerations apply to the inverse bandwidth.
DO NOT USE ANY OTHER METHOD IN CLASS NetworkSocket. THEY ARE SUBJECT
TO CHANGE.
Data Transfer Service
You are to implement two classes,
SW_Source and SW_Sink, that provide reliable byte
stream transfer to their users, SourceTester and SinkTester, and interact
only via the LRD channels defined above.
Class SW_Source implements the following public methods:
- Data variable: SourceTester
dtsource;
Pointer to the class that created object of class SW_Source.
- Constructor SW_Source( local
port, remote domain name and port, send buffer size ) in the following
format:
SW_Source (int aLocalPort, String aRemoteDN, int aRemotePort, int
aBufSize);
Constructs the source part of a sliding window data transfer protocol
(it would have send window, counters, timers, etc.). The send
buffer size is constant and indicates the number of bytes that SW_Source
must be prepared to buffer; this, together with the ackData(n) calls
(described below), allows the user to know the number of bytes that
it (the user) can foist on SW_Source.
- Method public void sendData(
byte[] data);
Accepts byte string from local user (for example, SourceTester) to be
transferred to remote user (for example, SinkTester). This method does
not block and should be called only when SW_Source has space to
buffer the data. If there is no space to buffer the data, it throws
an error (using throw new Error("buffer is full")). Note that
this method only transfers the data from the user to SW_Source
buffer. It does not wait for this data to be sent to the remote
site (non-blocking function).
The user of SW_Source
(i.e., Class SourceTester) implements the following method:
- Method public void ackData(int
n);
SW_Source calls this method to indicate that "n" bytes of data have
been acked. This allows the user to know how much data is still outstanding
and how much more data it can pass to SW_Source.
Class SW_Sink implements the
following methods:
- Data variable: SinkTester
dtsink;
Pointer to the class that created object of class SW_Sink.
- Constructor SW_Sink( local
port, remote domain name and port, receive buffer size ) in the following
format:
SW_Sink (int aLocalPort, String aRemoteDN, int aRemotePort, int
aBufSize );
Constructs the sink part of a sliding window data transfer protocol
(it would have send window, counters, timers, etc.). The receive
buffer size is constant and indicates the maximum amount of data (in
bytes) that the user (i.e., SinkTester) is prepared to buffer.
Calling the constructor is an implicit call to readyToAccept(aBufize).
- Method void readyToAccept(n);
Called by user to indicate that it is ready to accept "n" more bytes.
The user of SW_Sink (i.e.,
Class SinkTester) implements the following methods:
- Method void deliverData(byte
data[]);
SW_Sink calls this method to pass data to the user (presumably the data
is then dropped from SW_Sink's receive buffer). Length of "data" (determined
by data.length) has to be less than or equal to the number of bytes
that the user is ready to accept.
Application Layer Service
Application layer consists of
two classes SourceTester and SinkTester. SourceTester
(SourceTester.java)
sends a file to the SinkTester (SinkTester.java).
SinkTester flushes data every 64K and waits for 4 seconds where it cannot
accept any data. SinkTester exits if no data is received for 120 seconds.
Testing and Debugging
In this assignment, programs run on different machines and each program
may have multiple threads. The distributed property (or characteristic)
of networking programs complicates testing and debugging.
A research method is devised to test distributed systems. According to
this method, we specify the interactions between different entities of
a distributed system in a file, called service file. In this assignment,
eight different interaction types (figure 2) take place between the different
entities: four on the source side, which are the constructor, sendData,
closeSource and ackData; and four on the sink side, which are the constructor,
readyToAccept, closeSink and deliverData. Those interactions are illustrated
in Tester service class (Tester.java).
The specifications of the interactions describe the relations between
the eight interaction types. For example, the number of bytes delivered
to Sink's user cannot increase the number of bytes sent by Source's user.
An interaction is of the following format:
void <method-name> (<parameters>){
// print function name in log file
if (condition) {
// method body.
} else
throw new Error("<error message>");
}
After defining service methods, we need to correlate the network system
(SourceTester, SW_Source, SinkTester and SW_Sink) to Tester. Whenever
a call is issued to an entity method, an RMI call is issued to the corresponding
method in class Tester. For example, when SourceTester object
calls SW_Source.sendData, SW_Source.sendData method
issues an RMI call to Tester.sendData with the same parameters.
Consequently, a developer can determine the correctness of both source
and sink sides by checking that no errors were thrown during the execution
of Tester. (This is not totally correct, because the network system can
encounter a deadlock and yet no error has been thrown. So, we add
a condition: a file sent by Source has to be received)
Figure 2
At any single moment during
the execution of the network system, there are many threads running on
multiple machines. But in order to check the correctness of the network
system against Tester, we need to ensure that, at any moment, a single
thread in the network programs is running.
Class Tester provides a main
lock which is used to synchronize among different programs and threads.
When a thread locks the main lock, no other thread in the network system
can lock the main lock, unless the lock is released. For example, when
a thread in SW_Sink locks the main lock, SW_Source on a different machine
cannot lock the main lock until SW_Sink releases the lock. (If there is
no Tester, then each side (source or sink side) has its own lock).
- Class Tester (Tester.java)
provides the main lock with 4 methods:
- Provides methods to
lock and unlock the main lock:
- "void lock();":
locks the main lock.
- "void unlock();":
releases the main lock.
- Provides methods to
write to the log file:
- "void print(String
str);": writes string str to a log file named
"List.log".
- "void println(String
str);": writes string str followed by '\n' to
a log file named "List.log".
- Specifies the data transfer
service. It has two groups of methods: source group and sink group.
- Source group has
four methods:
- void Source(int,String,int,int):
called by the constructor of class SW_Source.
- void sendData(byte[]):
called by SW_Source.sendData method.
- void closeSource():
called by SW_Source.closeSource method.
- void ackData(int):
called by SourceTester.ackData method.
- Sink group has four
methods:
- void Sink(int,String,int,int):
called by the constructor of class SW_Sink.
- void readyToAccept(int):
called by SW_Sink.readyToAccept method.
- void closeSink():
called by SW_Sink.closeSink method.
- void deliverData(byte[]):
called by SinkTester.deliverData method.
Class Tester binds
itself (using Naming.rebind method) to rmiregistry with name "Tester"
and has the interface TesterInter (
TesterInter.java). Classes SourceTester and SinkTester do a lookup
(using Naming.lookup method) for "Tester). Afterwards, the four classes
SourceTester, SW_Source, SinkTester and SW_Sink can issue RMI calls to
the methods exported by Tester.
It is worthy to mention again,
that in order to issue an RMI call, the main lock has to be locked before
the call is issued.
Figure 3 illustrates the direction of interactions between different
entity of the network system (an arrow from entity A to entity B means
that A calls a method at B, and if the arrow sinks into a small back circle,
then this call is a remote call via the port name mentioned).
Figure 3
Assignment
Files - added 3/21/05
- Please copy hw5SourceFiles.zip.
When you expand the files, you will find the following files:
- Subdirectory
"Source" has the following files:
- SourceTester.java
- SW_Source.java
(a template is available in SW_Source.java).
- NetworkSocket.java
- TesterInter.java
- Subdirectory
"Sink" has the following files:
- SW_Sink.java
(a template is available in SW_Sink.java).
- NetworkSocket.java
- TesterInter.java
- Subdirectory
"Tester" has the following files:
- Tester.java
- TesterInter.java
- RWLock.java
(handles locking).
- security policy
file.
- Simple HTTP
class server.
How to start
- Implement "stop and wait"
data transfer protocol.
- Transfer a very small
file, 50 bytes.
- Transfer a file that
is smaller than the send buffer in order to test method SW_Source.sendData.
- Transfer a file bigger
than the buffer in order to test the correctness of your handling
of the buffer (calling SourceTester.ackData).
- Increase the send window,
but fix it to an arbitrary size. Then, handle sending and receiving
of data and acknowledgments.
- Increase the loss probability
(variable lossProb in NetworkSocket) at source side. Handle source resending
accordingly.
- Increase the loss probability
(variable lossProb in NetworkSocket) at sink side. Handle the acknowledgment
loss accordingly.
- Increase the duplication
probability (variable duplicateProb in NetworkSocket) at source side.
Handle duplication at sink side.
- Increase the reorder probability
(variable reorderProb in NetworkSocket) at source side. Handle reordering
at sink side.
- Change the sending window
from fixed window to adaptable window.
- Make random scenarios by
changing loss, reorder and duplicate probability variables in NetworkSocket
class.
This approach is not restrictive.
You can do it in a different way.
Don't be tempted to code everything at once.
Execution
- Inside hw5_yourLastName/Tester
directory
- Compile files ("javac
*.java").
- Execute "rmic Tester".
- Compile Source and Sink
files.
- Execute "rmiregistry &".
- Run the tester and bind
the server to "Tester":
%java -Djava.rmi.server.codebase=file:///hw5_yourLastName/Tester/
-Djava.security.policy=../policy Tester
You run the tester on a specific machine. If you start rmiregistry
at a different port (e.g., the default rmiport 1099 is used) by typing
"rmiregistry <rmiport>", then you need to change the port of Tester.java
to the correct one. The line to be changed can be found by searching
"YRY".
As an alternative, you can also use the class-server
(http server):
- Run the class http server at <hostname>:
%java examples.classServer.ClassFileServer <port> hw5_yourLastName/Tester/
-Run the tester:
%java -Djava.rmi.server.codebase=file:///<host name>:<port>/
-Djava.security.policy=../policy Tester
- Run the sink:
%java -Djava.security.policy=../policy SinkTester filename localPort
SourceHostName SourcePortNo
If your rmiregistry runs on a different machine, please adjust the lookup
method parameter to "//<hostname>:<rmiregistryPort>/Tester".
The line to be changed can be found by searching "YRY."
- Run the source:
%java -Djava.security.policy=../policy SourceTester filenameToBeSent
localPort SinkHostName SinkPortNo StreamOption
Similar to the sink, you may need to tell the source how to find RMI
registry.
Design Specifications
Your design specification should
demonstrate that you have thought about the problem and devised a plausible
solution. Your solution should be described in prose, but please use diagrams
or psuedo-code where appropriate. Clarity, concision and simplicity are
virtuous; length is not.
Your design should also include
a short description of how you will test your code to be sure it is correct.
Test design is very challenging for network programs given its distributed
nature. Be sure that you have designed tests that will accurately determine
whether your code works correctly, and check for edge/boundary cases.
Your design specification should
be submitted in hardcopy form as well as in online form by the deadline.
We will try our best to provide feedback in a timely manner to you.
Useful Reading
- A powerpoint presentation
about the assignment (hw5help.pdf)
Tester
class compiler error fix help
RMI
with Java SDK1.4 error fix help
- Sliding window protocols
- Read the note, Transport
Layer Principles (pdf). Adhering to data transfer
protocol mentioned in section 5 will save you a lot of time.
- Simulation of Sliding
window protocol ( 3-Column:)
and ( 5-Column).
- Java
- Note #1: notes
about threads and synchronization.
- Note #2: notes
about wait and notify.
Your source may need synchronization between the sending thread
and the receiving thread on the shared window. One method to implement
synchronization is to use Semaphore. An implementation of Semaphore
is available at YYYYYY - WILL BE ADDED LATER,
IF NEEDED. However, a simple solution, as already used in
the sample code, is to use Java object. For example,
Object lock = new Object();
...
synchronized (lock) {
// do things exclusively.
}
You can also use the lock object to implement wait
and notify, if you choose so.
- See The
Java Language Specification by James Gosling, Bill Joy and Guy
Steele. Read chapter 17, concerning "Threads and Locks".
Pay attention to how the term synchronized is used.
- See The
Java Language Specification by James Gosling, Bill Joy and Guy
Steele. Read chapter 11, concerning Exceptions.
Pay attention to the part of how to implement them.
- Classes Timer
and TimerTask
are important for timeouts.
- Java
resources
(Ideas heavily and liberally
borrowed from http://zoo.cs.yale.edu/classes/cs433/assignments/prog1/.
Thanks to Prof. Richard Yang of Yale-CS and University of Maryland-CS.)
Any student may be asked to
show and discuss his implementation in class, so be ready with your presentation.
Submit a zipped file of your source codes, scripts (to run your program)
and report along with a hardcopy of your source codes, scripts, a couple
of sample executions of your solution and report.
Use <hw#cs555_yourlastname_mmddyy.{zip,gz,ppt}>
as the naming convention for your zipped or ppt files when emailing your
submission to ajay.gupta@wmich.edu. Replace '#' with the appropriate homework
number.
REMINDER:
You
are responsible for making yourself aware of and understanding the policies
and procedures in the undergraduate
(pp. 268-270) [Graduate
(pp. 24-26)] Catalog that
pertain to Academic Integrity. Additionally,
easy availability of information, material, source codes, lecture notes
etc on the Internet may make it possible to find solutions to your assignments
on the Internet or elsewhere. It is okay to refer to those, understand
them and use them to enhance your solutions, generate your own ideas etc.
However, you must give proper and full credit to original authors of the
work, if you include their ideas. Failing to do so is part of academic
and professional dishonesty. It will not be tolerated in this class. Do
not give in to temptations....
|