UDP File Transfer - Receiver
This is what requests a file from a Sender and downloads it to a local machine. Just like with the other program you can twiddle with some of the hard coded arguments and replace them with command line ones in the
Main() function at the bottom.
Like with the Sender, in our constructor we create our
UdpClient with a default remote host set (which should be that of the Sender).
I mentioned in the last part that there is a
Connect method in
UdpClient (doc link). Please note that this is a dirty filthy lie as UDP is a connectionless protocol. In reality, what it does is set a "default remote host," for you so every time that you call this overload of the
Send method you don't need to specify where you want to go, as it will only go to that one host. This also applies to some of the constructors for
UdpClient (like the one we're using).
Shutdown() in this class will just request a cancel of an existing file transfer, you can see later in the
GetFile() method how this works.
GetFile() is the most important function of the class and its very similarly structured to
UdpFileSender.Run(). It's what does all of the communication with the Sender. Let's break it down. Up at the top of the function's body there are some variables for the file transfer state and a helper function to reset them if needed. In the beginning of the
while loop we check for any new
NetworkMessages. First checking if the latest received
Packet is a
BYE, it then passes that onto the
switch statement. Inside of the
switch is what manages the state of the file transfer (
REQF, wait for
ACK, wait for
ACK, etc...). Inside of the
case it will empty the
Block request queue, check for any
SEND messages (i.e.
Block data). If the request queue is empty but we don't have all the
Blocks, it will refill the request queue with the missing
Block.Number values. But if we have all of the
Blocks, then we move onto the state where we say
BYE to the Sender (so it can accept new transfers) and then we reconstruct the
Blocks into a byte array, uncompress them, and save the file. At the end of the function we make a check to see if the transfer was ended prematurely by user request or the Sender.
Close() will clean up the underlying network resources, which is just the
_checkForNetworkMessages() is identical to the one seen in Sender. It sees if there are enough bytes for a
Packet message then queues it up for processing.
_saveBlocksToFile() is where we take the
Blocks, reassemble them, uncompress the data, verify it with a checksum and then save it to the disk.