Program Description and RequirementYou will be implementing an RDT protocol on top of UDP. You will also make an Application that will have a Client download an EXE file from a Server and then execute that file. The Client and Server will both be console programs.There will be 4 major classes, one per file:(1) RDTServer classwaits for a Client to connect; once contacted, grab a random EXE file and send it the Client. After the exchange takes place, the Server shuts down.First, it sends the file name, NOT null-terminated (MSG_FILE_NAME).Next, it sends the file content (MSG_FILE_DATA), in 256-byte chunks, except the last chunk.Finally, it sends the MSG_FILE_DONE message.public class RDTServer{public static int progNumToSend = 1;private RDT3 rdt;private FileInputStream inFile;private String filename;public RDTServer(String ipAddress, int receivePort, int peerReceivePort)throws Exception{rdt = new RDT3(ipAddress, receivePort, peerReceivePort);Thread.sleep(100);}/**This is the run method*/public void run() throws Exception{try{System.out.println(Started the Server.);getRequest();filename = App.getRandomExeFile();if ( filename == null ){}else{sendFileName();}}catch (Exception e){}finally{//shut down the Server properly}} //run()/**This method uses a while loop to send data chunks by calling rdt.sendData().*/private void sendFile() throws Exception{}
/**This method sends the file name by calling rdt.sendData().*/private void sendFileName(){}/**This method uses a while loop and waits until a request has been received bycalling rdt.receiveData().*/private void getRequest(){}/**The main() instantiates an instance of RDTServer.*/public static void main(String[] args){}}The Server uses getRandomExeFile() provided in App class to get the filename of a file to download. To open the file, you need the path (EXE_SUBFOLDER ) prepended, such as: inFile = new FileInputStream(App.EXE_SUBFOLDER + fileName);Shut down the Server as follows, this also shuts down all their Threads.Thread.sleep(2000); // Give protocols time to finishSystem.out.println(Shutting down.);System.exit(0);(2) RDTClient classcontacts the Server, downloads an EXE file, executes the EXE file, and shuts down thesame way as the Server (see the codes above). To run the EXE in the Client after it has been received, do thefollowing: Runtime.getRuntime().exec(fileName);public class RDTClient{private RDT3 rdt;private String filename;private FileOutputStream outFile;public RDTClient(String ipAddress, int receivePort, int peerReceivePort)throws Exception{rdt = new RDT3(ipAddress, receivePort, peerReceivePort);Thread.sleep(100);}// Client run methodpublic void run() throws Exception{sendFileRequest();if ( getFilename() ){//new a FileOutputStream and continuously call rdt.receiveDate() to get file chunks.//run the EXE file when it is well-received.}}catch (Exception e){}finally{//shut down the Client properly.}}
/**This method sends a request by calling rdt.sendData().*/private void sendFileRequest(){}/**This methods loops and waits for the filename sent from the Server by callingrdt.receiveData()*/private boolean getFilename(){}/**The main method instantiates an instance of Client.*/public static void main(String[] args){}}(3) App classhas common data and routines for the Client and Server. An application message consists of a one-byte type followed by the data. The types are as follows.MSG_REQUEST_EXE_FILE = 1Sent from the Client, has no dataStarts the session says that Client wants an EXE.MSG_FILE_NAME = 2Sent from the Server, has file name as the data NOT null-terminated.The Client will make an output file using this name. The data from MSG_FILE_DATA segments will be written to this file.MSG_FILE_DATA = 3Sent from the Server, has 1 to 256 bytes of file dataMSG_FILE_DONE = 4Sent from the Server, has no data.Indicates the last piece of file data was sent.Server shuts down. Client executes the received file and shuts down.MSG_NO_EXE_FILE_AVAILABLE = 5Indicates the Server had no EXE files in the folder.Both sides will print appropriate messages and shut down.Use the codes below:public class App{// Application Message Typespublic static final byte MSG_REQUEST_EXE_FILE = 1;public static final byte MSG_FILE_NAME = 2;public static final byte MSG_FILE_DATA = 3;public static final byte MSG_FILE_DONE = 4;public static final byte MSG_NO_EXE_FILE_AVAILABLE = 5;// Application message maximum sizespublic static final int MAX_DATA_SIZE = 256;public static final int MAX_MSG_SIZE = MAX_DATA_SIZE + 1;// Recevier port numberspublic static int CLIENT_RCV_PORT_NUM = 5281;public static int CLIENT_PEER_RCV_PORT_NUM = 7281;public static int SERVER_RCV_PORT_NUM = 7281;public static int SERVER_PEER_RCV_PORT_NUM = 5281;// Exe programs subfolder assuming the subfolder name is Progspublic static String EXE_SUBFOLDER = .\Progs\;
/*** Returns a random EXE file name from EXE_SUBFOLDER.* If there are no EXE files in Progs, null is returned.* The file name doesnt have the path.* @return a random EXE filename or null.*/public static String getRandomExeFile(){java.io.File dir = new java.io.File(EXE_SUBFOLDER);String [] entireFileList = dir.list();String [] exeFileList = new String[entireFileList.length];int exeCount = 0;for( int i = 0; i < entireFileList.length; i++ ){if( entireFileList[i].toLowerCase().endsWith(.exe) ){exeFileList[exeCount++] = entireFileList[i];}}if(exeCount == 0)return null;int index = new java.util.Random().nextInt(exeCount);return exeFileList[index];}}(4) RDT3 classimplements the Reliable Data Transfer protocol on top of UDP using the basics of the RDT 3.0from the textbook with some minor modifications. In addition, we will build in some error injection to test robustness. This class will have Sender and Receiver tasks that are based on the state machines from the lecture. These will be embedded classes in RDT3 so they can access the state variables in RDT3. This class CANNOT access App or RDTClient or RDTServer class. Both the Client and Server will use this exact same RDT3 class. This class should not care what application usdes it.Whenever an error is injected, a message starting with ???? is printed out. When a bad packet for the Receiver is received or a bad ACK for the Sender is received, then a message starting with !!!! is printed. You will print lots of other messages to help tracking what is going on, but ONLY these messages can start with ? or !.???? Checksum altered for Testing Purposes.???? ACK dropped for Testing Purposes.!!!! Rcv data bad resend prev ACK.!!!! BAD ACK received.Below are required pieces for this class. You need to comment and fill in. You CANNOT add or remove any ???? or !!!! messages. The peer is the other host/end system. The sender of this side communicateswith the peer receiver and vice versa. The App Layer calls sendData if it wants to send data to its peer. The data gets sent from this Sender to the peers Receiver. The App Layer calls receiveData to get data sent from peer Sender and received by this Receiver. A RDT3 segment has a one byte header followed by the APP datafollowed by a one byte checksum: Header | App Data | Check sumThe one-byte header has two relevant bits: Bit 0: Sequence number, either 0 or 1Bit 1: ACK bit, 1 = ACK, 0 = App Data segmentThe checksum is the bitwise XOR of the Header and App Data and is appended as the last byte of the segment. When the receiver gets the segment, it performs the checksum on the entire segment and shouldget 0!You CANNOT add any other state variables besides those listed below for each class. You can (and should) add more methods; however, the methods I give you must be used as is and cant be modified except to comment them more. Recall that a datagram has the length in it: receivePacket.getLength()
public class RDT3{static private final int SEQ_MASK = 1; // 2 to the 0th power bit 0static private final int ACK_MASK = 2; // 2 to the 1st power bit 1private InetAddress peerIpAddress;private int rcvPortNum;private int peerRcvPortNum;private boolean dataWaitingToBeSent = false;private boolean dataWasReceived = false;private byte[] dataToSend;private byte[] dataReceived;public RDT3( String peerIP, int _rcvPortNum, int _peerRcvPortNum )throws java.net.UnknownHostException{rcvPortNum = _rcvPortNum;peerRcvPortNum = _peerRcvPortNum;peerIpAddress = InetAddress.getByName( peerIP );new Sender().start();new Receiver().start();}public void sendData( byte[] data ){while ( dataWaitingToBeSent ){Thread.yield(); // Wait until its ready for the next packet}dataToSend = data;dataWaitingToBeSent = true;}public byte[] receiveData(){// You write this one, similar to sendData.// Uses dataWasReceived and dataReceived.}private byte checkSum( byte[] data, int len ){byte cs = 0;// You write the middle loop through and XOR all the bytes// into cs. The XOR operator is ^if( oneInN_Occurs(20) ){System.out.println( ???? Checksum altered for Testing Purposes. );cs = (byte)(cs + 1); // Bad Checksum error to test RDT robustness}return cs;}// Random true with probability 1 in Nprivate boolean oneInN_Occurs( int n ){if ( n <= 1 ){return true;}return new java.util.Random().nextInt( n ) == 0;}private class Receiver extends Thread{private DatagramSocket receiverSocket;private byte[] receiveData = new byte[2 * App.MAX_DATA_SIZE];private DatagramPacket receivePacket;private int expectedSeqNum = 0;@OverrideCS3830 Fall 2014 Dr. Lily Chang6 | P a g epublic void run(){try{receiverSocket = new DatagramSocket( rcvPortNum );System.out.println( Started Receiver. );}catch ( Exception ex ){System.out.println( Cant start Receiver: + ex.toString() );System.exit( 1 );}while ( true ){try{// Implement the RDT 2.2 Receiver make some methods.// Data received is good if:// checksum is 0, seq # is expected, ACK bit is 0// If data received is not good, output the message:// !!!! Rcv data bad resend prev ACK// A slight change from RDT 2.2:// Dont send the ACK until after the App layer retrieves// the data. So when a good packet is received, do:// dataWasReceived = true;// while ( dataWasReceived )// Thread.yield();// This will sit and wait until the APP layer gets the data,// after which you will send the ACK.// You need to understand why!}catch ( Exception ex ){System.out.println( Error in Recv loop: + ex.toString() );}}}// Ill give you this one it has the error injection in itprivate void sendAck( int ackNum ){if ( oneInN_Occurs( 10 ) ){System.out.println( ???? ACK dropped for Testing Purposes. );return; // Lose ACK inject erros to test RDT robustness}try{final int dataLen = 2;byte[] data = new byte[dataLen];data[0] = (byte) (ackNum + ACK_MASK);data[1] = data[0]; // 2 bytes = Checksum is the same as byte[0]// You finish get port from receivePacket}catch ( Exception ex ){System.out.println( Rcv Error sending ACK: + ex.toString() );}}} // end Receiver classprivate class Sender extends Thread{private DatagramSocket senderSocket;private byte[] rcvData = new byte[4]; // Only gets ACKs backprivate DatagramPacket rcvPacket;private int curSeqNum = 0;CS3830 Fall 2014 Dr. Lily Chang7 | P a g e@Overridepublic void run(){// Make a senderSocket similar to how receiverSocket was// made in Receiver, except the DatagramSocket wont// take a port number parameter.while ( true ){try{// Implement the RDT 3.0 Sender make some methods.// If the ACK received is bad, then output the message:// !!!! BAD ACK received.// Technically, if it is bad, you dont know if it is an// ACK or not, but the Sender is only supposed to receive ACKs.// One small change from RDT 3.0: restart the timer on bad ACK.// For the timer, set socket timeout before the receive call as:// senderSocket.setSoTimeout( 500 );// If it throws the exception, it has timed out and you// need to resend the packet.// Note: Datagrams are sent to (peerIpAddress, peerRcvPortNum)}catch ( Exception ex ){System.out.println( Error in Sender loop: + ex.toString() );}}}// Ill write part of this it has error injection.private void sendPacket(){try{int dataLen = 2 + dataToSend.length;byte[] data = new byte[dataLen];data[0] = (byte) curSeqNum;// You finish it copy data and append checksum (call checkSum).System.out.println( Sender sent data pkt: + curSeqNum );}catch ( Exception ex ){System.out.println(Sender send packet failed: + ex.toString());}}} // end Sender class} // end RDT3 classThe Client and Server are both one-shot, not infinite loops. If there is not an EXE file on the Server, then the MSG_NO_EXE_FILE_AVAILABLE is sent and both sides shut down. The Client and Server MUST use RDT3 for all sending and receiving (sendData, receiveData). They CANNOT have DatagramSocket, DatagramPacket, or anything related to these anywhere. Use Thread.yield() when you are looping waiting for a variable to change.Additional Notes1. You MUST follow the software development ground rules from CS2430 (posted on D2L.) Name all your constants (except for the constants I gave you.)
Reviews
There are no reviews yet.