Beruflich Dokumente
Kultur Dokumente
Although the wise thing to do is to use existing protocols whenever the task you want to do is solved
by one of them we are about to do the opposite here. After all, this is just an excuse for you to do
some coding.
The Protocol
In order to submit some files to a certain server, users employ a simple UDPbased program that
sends a given file to the server. The protocol used is quite simple and it does not allow to name the
received file.
File transfer splits the original file as a sequence of 512 byte blocks. The client starts sending the
first block. To signal the end of the file the client sends a datagram that contains the next block
number but no data. In the Figure 1 we can see that blocks from #1 to #4 seem to be same size, but
the last data block, #5 is slightly smaller as it contains the last bytes of the file that happen to be less
than 512 bytes. There is an extra datagram, #6, that contains no file data at all. The server detects
this condition as the end of the file transfer.
Original file
#0 #1 #2 #3 #4 #5 #6
Figure 1: File is split into a sequence of blocks. All of them equal size
but maybe the last one.
Each datagram data starts with a fourbyte block number. After receiving one block the receiver
sends a datagram containing the same four bytes containing the block number. Upon receiving this,
the client is allowed to send the next data block.
datagram data
(up to 512 bytes)
Figure 2: Each one of the above blocks has
this structure. Answers from the server do not
contain any data, just the block number.
The client code is provided so you can concentrate on writing the server code. Please note that
filename is not transferred and server just names each file with a sequence number with the syntax
“received###” where each '#' is a decimal digit. The first received file name will be “received000”,
the second “received001” and so on. If more than 1000 files are received the filename will wrap
around and some files will be overwritten.
The server
Your work consist on creating the server code so it can handle a single client at a time (you might
want to create a concurrent version able to handle several clients at a time if you like challenges
though). The server has 10 seconds “giveup” timer so if any file upload operation runs amok the
server will return to the “wait for a new file” state (the same as if the last upload ended
successfully).
It is suggested you use the method setSoTimeout(time_in_ms) of DatagramSocket's class to achieve
a timelimited blocking call when calling to the receive() method. If you do nothing, receive()
blocks forever till a datagram is received. However, by using the setSoTimeout() method you can
limit the maximum amount of time receive() call will wait for an incoming datagram. Once the
timeout period has expired an exception will be raised. You can catch that exception to handle the
proper actions when the server times out.
Some tips:
● Assume that files are no larger than 2.199.023.255.552 bytes.
● Please add your full name as a comment in the first line of code.
● Send your server's source code using the provided client to my server msanchez.upv.es.
● In case of lost datagram the server will recover itself because the timer, but the client will
hang. This is the expected behavior.
● Remember that method getAddress from DatagramPacket class provides you the source
address the datagram was received from.
● If the server receives a datagram with a number different than the expected block number it
has to abort the current transfer, returning to the “wait for a new file” status.
Due date
This work is due by Monday January, 15th, 2007.
The client code
import java.net.*;
import java.io.*;
public class A2client {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(8888);
int bytes, block = 0;
InetAddress dir = InetAddress.getByName(args[0]); // destination address
FileInputStream fis = new FileInputStream(args[1]);// origin file to be transmitted
byte[] buffer = new byte[512+4];
while((bytes = fis.read(buffer,4,512)) > 1 ) {
System.out.println( "Sending block = " + block);
intToByteArray(buffer,block);
DatagramPacket p = new DatagramPacket(buffer, bytes+4, dir, 7777);
ds.send(p); // send datagram
ds.receive(p); // wait for answer
if(block != byteArrayToInt(buffer) ) {
System.out.println("Protocol error ... exiting the program");
System.exit(10);
}
block++;
} // done with the file, let's signal the end of transfer (no wait for ACK here)
intToByteArray(buffer,block);
DatagramPacket p = new DatagramPacket(buffer, 4, dir, 7777);
ds.send(p);
}
// some magic to put and retrieve the block number from the buffer
public static int byteArrayToInt(byte[] b) { // takes the first four bytes
int value = 0; // of the buffer and turns them
for (int i = 0; i < 4; i++) { // into an integer value (32 bits)
int shift = (4 1 i) * 8;
value += (b[i] & 0x000000FF) << shift;
}
return value;
}
public static void intToByteArray(byte [] b, int value) {
for (int i = 0; i < 4; i++) { // writes four bytes representing
int offset = (b.length 1 i) * 8;// an integer value
b[i] = (byte) ((value >>> offset) & 0xFF);
}
}
}