For the Java version, the starter files are below. Changes should only be made to the wclient.java file.
The HUMP option is the best way to handle NAT firewalls, which is why we're doing it.I have old C# versions of the above files, but I would need to update them to supporting HUMP. But let me know if this is an issue for you..
Your assignment is to do the following, by modifying and extending the wclient.java outline file:
For BUMP, in which the server answers from a previously unseen port, it is helpful to view the description in terms of the state diagram. We will use the states UNLATCHED, ESTABLISHED and DALLY used to describe TFTP in intronetworks.cs.luc.edu/current/html/udp.html#tftp-states.
UNLATCHED
Transition to ESTABLISHED on receipt of a valid Data[1]
packet (correct source IP address, etc)
Save the source port as latchport
ESTABLISHED
At any point we are expecting block expected_block
If we receive a valid full-sized Data[N] packet with
N==expected_block, increment expected_block.
The source port must match latchport.
If we receive a valid Data[N] with N==expected_block
and with size < 512 bytes, transition to DALLY
DALLY
If we receive a valid Data[N] from the correct port,
with N == expected_block, resend the last ACK
Exit this state after sufficient elapsed time
For HUMP, there is no clear UNLATCHED state where you're waiting for a packet from a port that is not known. However, we might call everything before the client sends ACK[0] the UNCONNECTED state, and everything following (until the end of the file) the CONNECTED state.
You can test your program by contacting the server, ulam.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. By asking port 4715 for the following names, you get the indicated behavior:
vanilla Normal transfer
In order to get the basic vanilla transfer working, there are three things you absolutely need to do, as outlined above:
The first steps are to fix the ACK port, by appropriate placement (two places!) of something like
ackDG.setPort(newport);
You can put this in with the other ackDG settings. At this point, in the SERVERPORT case you should now get Data[1] and Data[2]. Because your repeated ACK[1]'s are now going to the correct port, you should get multiple Data[2]'s, because each time you send ACK[1] the server will respond with Data[2]. This behavior is quite similar, overall, to that of the SAMEPORT setting without the above fix.
(If you're using the SAMEPORT case because you're at home and you have a NAT router, that's fine, but you should still make the above fix anyway, and then come in to Loyola to verify that the SERVERPORT case works properly. Having the SERVERPORT case work is a requirement.)
The second step is to increment expected_block, so that the arrival of Data[2] results in ACK[2] rather than ACK[1]. This is done with
expected_block++;
You can put this anywhere after the "// send ACK" code block inside the main while loop.
At this point you should get the entire file (11 blocks), with timeouts at the end because you are not properly handling the end-of-transmission case (last block has < 512 bytes of data). Because repeated ACK[11]'s don't trigger any new transmissions at the server side (why?), you won't get multiple copies of the last packet.
In general, you should verify that the arriving block number matches expected_block, as part of other sanity checks, before incrementing the latter. But you can worry about that later.
The next steps are to implement the sanity checks. The most important are to check the incoming port and also the packet's block number (to see that it matches expected_block), but you should also check the packet's IP address and size and opcode (watch the order!).
Here are a few options for earning extra credit. In order to receive extra credit, your project must be submitted by the due date. You must also make it clear, near the top of your wclient.java file, that you are submitting an extra-credit option. (I may add to this list if I can think of others.)
1. Implement sliding windows. A simple implementation is outlined in the Sliding Windows chapter of my book.
2. Implement adaptive timeout. That is, measure the RTT of each packet, and create a running average RTTmean, and then set the timeout interval to, say, 2*RTTmean. You should probably set a minimum timeout of, say, 500 ms.
If you're interested in this option, let me know and I'll create a larger file to use for testing.