WUMP Programming Project
This program is for those registered for graduate
credit, that is, Comp 443. Those
who are currently taking Comp 170 (or have not taken it yet) can contact me
about other options.
The project is to implement the BUMP client in java, with window
size 1. Here is an overview of the three
WUMP protocols (BUMP, HUMP, and CHUMP).
For the Java version, here are the files wumppkt.java,
containing the packet format classes, and wclient.java,
which contains an outline of the actual program. There is now a C#
version, in wumppkt.cs and wclient.cs.
For either language, only the wclient file should be modified; you should not
have to make changes to wumppkt.
Your assignment is to do the following, by modifying and extending the
wclient outline file:
- Implement the basic transfer
- Add all appropriate packet sanity checks: timeouts, host/port, size,
opcode, and block number
- Generate output. The transferred file is to be written to System.out.
A status message about every packet (listing size and block number) is
to be written to System.err. Do not
confuse these!
- Terminate after a packet of size less than 512 is received
- Implement an appropriate "dallying" strategy
- send an ERROR packet if it receives a packet from the wrong port. The
appropriate ERRCODE in this case is EBADPORT.
An outline of the program main loop, with notes, is
available here
.
I recommend that you implement this in phases, as follows.
- Latch on to the new port: save the port number from Data[1], and make
sure all ACKs get sent to this port. This will mean that the transfer
completes. You should also make sure the client stops when a packet with
less than 512 bytes of data is received. Unless you properly record the
source port for Data[1], you have no place to which to send ACK[1]!
- For each data packet received, write the data to System.out. All
status messages should go to System.err, so the two data streams are
separate if stdout is
redirected. To write to System.out, use System.out.write:
System.out.write(byte[]
buf, int offset, int length);
For your program, offset will be 0, buf will typically be
dpacket.data(), where dpacket is of type DATA (wumppkt.DATA). The length
will be dpacket.size() - wumppkt.DHEADERSIZE (or, equivalently,
dg.getLength() - wumppkt.DHEADERSIZE, where dg is a DatagramPacket
object).
- Add sanity checks, for (in order) host/port, packet size, opcode, and
block number.
- Handle timeouts, by retransmitting the most recently sent packet when
the elapsed time exceeds a certain amount (4 seconds?). One way to do
this is to keep a DatagramPacket variable LastSent, which can either be
reqDG or ackDG, and just resend LastSent. Note that the response to an
InterruptedIOException, a "true" timeout, will simply be to continue the
loop again.
- Add support for an dallying and error packets. After the client has
received the file, dallying means to wait 2.0 - 3.0 timeout intervals
(or more) to see if the final data packet is retransmitted. If it is, it
means that the final ACK was lost. The dally period gives the client an
opportunity to resend the final ACK. Error packets are to be sent to any
sender of an apparent data packet that comes from the wrong port.
You can test your program by contacting the server, ulam2.cs.luc.edu,
and requesting files. If you contact on port 4715, you get a response from
a new port (the standard behavior). This doesn't go through NAT firewalls,
so if you contact ulam2 on port 4716 you get a response
from the same port. No matter what file you ask for, the file
you get is always the same. However, by asking port 4715 for the following
names, you get the indicated behavior:
vanilla Normal transfer
- lose Lose everything
after the first windowful (min 3). It will be retransmitted when you
retransmit the previous ACK.
- spray Constant barrage of
data[1]. Implies LOSE too. In this case, no timeout events will occur;
you must check for elapsed time.
- delay Delays sending packet 1,
prompting a duplicate REQ and thus results in multiple server instances
on multiple ports.
- reorder Sends the first windowful in the wrong
order. You're probably not implementing windows.
-
- dupdata2
- DATA[2] is sent twice
- losedata2
- DATA[2] is lost on initial send, until you resend ACK[1]
- marspacket
- A packet from the wrong port (a "martian" port) arrives
- badopcode
- a packet arrives with an incorrect opcode
- nofile
- you get an error packet with a NO FILE error code.
At this point, the only ones that work on port 4716 are vanilla,
lose2 (losedata2) and dup2 (dupdata2).