BUMP implementation in Java.docx
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). Here are the files wumppkt.java, containing the packet format classes, and wclient.java, which contains an outline of the actual program. Only the latter file should be modified; you should not have to make changes to wumppkt.java.
What you are to do is the following, by modifying and extending the wclient.java 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 is attached
recommended that you implement this in phases, as follows.
1. 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]!
2. 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).
3. Add sanity checks, for (in order) host/port, packet size, opcode, and block number.
4. 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.
5. 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.
vanilla Normal transfer
lose Lose ever ...
BUMP implementation in Java.docxThe project is to implemen.docx
1. BUMP implementation in Java.docx
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). Here are the
files wumppkt.java, containing the packet format classes,
and wclient.java, which contains an outline of the actual
program. Only the latter file should be modified; you
should not have to make changes to wumppkt.java.
What you are to do is the following, by modifying and
extending the wclient.java 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 is attached
recommended that you implement this in phases, as follows.
1. 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]!
2. For each data packet received, write the data to System.out.
All status messages should go to System.err, so the two data
2. 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).
3. Add sanity checks, for (in order) host/port, packet size,
opcode, and block number.
4. 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.
5. 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.
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
3. 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).
wumppkt.javawumppkt.java// The following implements the pac
ket formats for BUMP and HUMP.
// Each individual packet type derives from class BASE, contain
ing
// protocol and opcode fields only; we don't really use this inher
itance
// hierarchy though.
// packets can be constructed with the applicable constructors;
// each ctor requires parameters for the necessary fields.
// when possible, there is a "convenience" ctor setting proto = B
UMPPROTO.
// The "raw" packet format, as sent and received via DatagramS
ocket,
// is byte[]. Packets (at least those that one might *receive*)
// can be constructed from a byte[]. For DATA packets, we also
need
// to specify the length of the packet, not necessarily the same a
4. s
// the length of the byte[] buffer.
// All packet classes also have a write() member function that
// writes out the packet fields into a byte[], for sending.
//import java.lang.*; //pld
//import java.net.*; //pld
//import java.lang.System.*;
import java.io.*;
publicclass wumppkt {
publicstaticfinalshort BUMPPROTO =1;
publicstaticfinalshort HUMPPROTO =2;
publicstaticfinalshort CHUMPPROTO=3;
publicstaticfinalshortREQop=1;
publicstaticfinalshortDATAop=2;
publicstaticfinalshortACKop=3;
publicstaticfinalshortERRORop=4;
publicstaticfinalshortHANDOFFop=5;
publicstaticfinalshort SERVERPORT =4715;
publicstaticfinalshort SAMEPORT =4716;
publicstaticfinalint INITTIMEOUT =3000;// milliseconds
publicstaticfinalint SHORTSIZE =2;// in bytes
publicstaticfinalint INTSIZE =4;
publicstaticfinalint BASESIZE =2;
publicstaticfinalint MAXDATASIZE=512;
publicstaticfinalint DHEADERSIZE = BASESIZE + SHORTSI
ZE + INTSIZE;// DATA header size
publicstaticfinalint MAXSIZE = DHEADERSIZE + MAXDAT
ASIZE;
5. publicstaticfinalint EBADPORT =1;/* packet from wrong port
*/
publicstaticfinalint EBADPROTO =2;/* unknown protocol */
publicstaticfinalint EBADOPCODE=3;/* unknown opcode */
publicstaticfinalint ENOFILE =4;/* REQ for nonexistent file
*/
publicstaticfinalint ENOPERM =5;/* REQ for file with wron
g permissions */
staticint proto(byte[] buf){
return buf[0];
}
staticint opcode(byte[] buf){
return buf[1];
}
publicstaticvoid w_assert(boolean cond,String s){
if(cond)return;
System.err.println("assertion failed: "+ s);
java.lang.System.exit(1);
}
//***************************************************
*********************
publicclass BASE {//implements Externalizable {
// don't construct these unless the buffer has length >=4!
// the data:
privatebyte _proto;
privatebyte _opcode;
//---------------------------------
6. public BASE(int proto,int opcode){
//super(); // call to base ctor
_proto =(byte) proto;
_opcode =(byte) opcode;
}
public BASE(byte[] buf){// constructs pkt out of packetbuf
}
public BASE(){}// packet ctors do all the work!
publicbyte[] write(){// not used
returnnull;
}
publicint size(){
return BASESIZE;
}
publicint proto(){return _proto;}
publicint opcode(){return _opcode;}
}
//*******************
publicclass REQ extends BASE {
privateshort _winsize;
privateString _filename;
//---------------------------------
public REQ(int proto,int winsize,String filename){
super(proto,REQop);
_winsize =(short) winsize;
_filename = filename;
9. publicint size(){
returnsuper.size()+ SHORTSIZE + INTSIZE;
}
public ACK(byte[] buf){}// not complete but not needed
}
//*******************
publicclass DATA extends BASE {
privateint _blocknum;
privatebyte[] _data;
//---------------------------------
public DATA(int proto,int blocknum,byte[] data){
super(proto,DATAop);
_blocknum = blocknum;
_data = data;
}
public DATA(int proto,int blocknum,byte[] data,int len){
super(proto,DATAop);
_blocknum = blocknum;
_data = data;
}
public DATA(byte[] buf,int bufsize){
this(BUMPPROTO, buf, bufsize);
}
// for building a DATA out of incoming buffer:
public DATA(int proto,byte[] buf,int bufsize){
super(proto,DATAop);
10. ByteArrayInputStream bais =newByteArrayInputStream(buf,0, b
ufsize);
DataInputStream dis =newDataInputStream(bais);
try{
int p = dis.readByte();
w_assert(p==proto,"Expecting proto "+ proto +", got "+
p);
int o = dis.readByte();
w_assert(o==DATAop,"Expecting opcode=DATA, got "
+ o);
int pad=dis.readShort();
_blocknum =(dis.readInt());
_data =newbyte[dis.available()];
dis.read(_data);
}catch(IOException ioe){
System.err.println("DATA packet conversion failed");
return;
}
}
public DATA(int proto){// for creating "empty" DATA objects
super(proto,DATAop);
_blocknum =0;
_data =newbyte[MAXDATASIZE];
}
public DATA(){this(BUMPPROTO);}
publicint blocknum(){return _blocknum;}
publicbyte[] data(){return _data;}
publicbyte[] write(){// not complete but not needed
returnnull;
}
publicint size(){