Advertisement
Guest User

Untitled

a guest
Jun 26th, 2017
55
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 7.65 KB | None | 0 0
  1. import java.io.*;
  2. import java.net.*;
  3.  
  4.  
  5. public class Sender extends Thread
  6. {
  7.     private static final int PORT_NUMBER = 4273;    //port to send to
  8.     private DatagramSocket sock;                    //sender socket
  9.     private DatagramPacket rcvPacket;               //ACK to be received
  10.     //private File clientfile;                      //file to be sent
  11.     //private String targethost;                    //connecting host for sender
  12.     //private int windowsize;                       //size of window
  13.     //private int timeout;                          //timeout in milliseconds
  14.     //private int payload;                          //size of payload in bytes
  15.     private byte[] file;                            //entire clientfile in bytes
  16.     private byte[] data;                            //data to send from clientfile
  17.     private byte[] buffReceive = new byte[20];      //only gets ACKs back
  18.     private int seqnum = 1;                         //current sequence number
  19.  
  20.  
  21.     /**
  22.      * This constructor sets up the sender then runs it
  23.      * @param clientfile - file to be sent
  24.      * @param targethost - who we are sending the file to
  25.      * @param windowsize - size of window
  26.      * @param timeout - timeout in millisecons
  27.      * @param payload - size of payload in bytes
  28.      */
  29.     public Sender(File clientfile, String targethost, int windowsize, int timeout, int payload)
  30.     {
  31.         try
  32.         {
  33.             run(clientfile, targethost, windowsize, timeout, payload);
  34.         }
  35.         catch(Exception e)
  36.         {
  37.             System.out.println("Unable to set up sender: " + e.toString());
  38.         }  
  39.     }
  40.  
  41.     /**
  42.      * This method will start the sender
  43.      */
  44.     public void run(File clientfile, String targethost, int windowsize, int timeout, int payload)
  45.     {
  46.         boolean dataToSend = true;
  47.         try
  48.         {  
  49.             sock = new DatagramSocket();
  50.             System.out.println("Sending to: " + targethost + "    Port: " + PORT_NUMBER);
  51.             file = getBytesFromFile(clientfile); //convert file into bytes
  52.         }
  53.         catch (Exception e)
  54.         {
  55.             System.out.println("Unable to start sender: " + e.toString());
  56.         }
  57.         while (true)
  58.         {
  59.             try
  60.             {
  61.                 if (dataToSend)
  62.                 {
  63.                     //send the data and determine if theres more to send after this packet
  64.                     dataToSend = sendData(targethost, payload);
  65.                    
  66.                     if (dataToSend)
  67.                     {
  68.                         //set socket timeout
  69.                         sock.setSoTimeout(timeout);
  70.  
  71.                         //receive ACK
  72.                         rcvPacket = new DatagramPacket(buffReceive, buffReceive.length);
  73.                         sock.receive(rcvPacket);
  74.  
  75.                         receiveACK();
  76.                     }
  77.                 }
  78.                 else
  79.                 {
  80.                     //send a terminating packet
  81.                     sendTerminator(targethost, timeout);
  82.                     return;
  83.                 }
  84.             }
  85.             catch (SocketTimeoutException e)
  86.             {
  87.                 System.out.println("Failed to send packet #" + seqnum);
  88.                 System.out.println("Retransmitting...\n");
  89.                 if (!dataToSend)
  90.                 {
  91.                     dataToSend = true;
  92.                 }
  93.             }
  94.             catch(Exception e)
  95.             {
  96.                 System.out.println("Sender send packet failed: " + e.toString());
  97.             }
  98.         }
  99.     }
  100.  
  101.     /**
  102.      * This method will shutdown the sender
  103.      * @return - true when the socket is closed
  104.      */
  105.     public boolean shutdown()
  106.     {
  107.         System.out.println("Shutting down sender...");
  108.         sock.close();
  109.         return true;
  110.     }
  111.  
  112.  
  113. /**Private Helper Methods****************************************************************************************************************/ 
  114.  
  115.     /**
  116.      * This method will return the clientfile in bytes
  117.      */
  118.     private byte[] getBytesFromFile(File clientfile) throws IOException
  119.     {
  120.         InputStream stream = new FileInputStream(clientfile);
  121.  
  122.         long length = clientfile.length();
  123.  
  124.         byte[] bytes = new byte[(int)length];
  125.  
  126.         int offset = 0;
  127.         int numRead = 0;
  128.         while (offset < bytes.length && (numRead=stream.read(bytes, offset, bytes.length-offset)) >= 0)
  129.         {
  130.             offset += numRead;
  131.         }
  132.  
  133.         if (offset < bytes.length) {
  134.             throw new IOException("Could not completely read file " + clientfile);
  135.         }
  136.  
  137.         stream.close();
  138.         return bytes;
  139.     }
  140.  
  141.     /**
  142.      * This method will return a segment of the file
  143.      * @param file - where the data is coming from
  144.      * @param payload - the amount of data to get in bytes
  145.      * @return - the data to be put into the packet
  146.      */
  147.     private byte[] getDataToSend(byte[] file, int payload)
  148.     {
  149.         try
  150.         {
  151.             byte[] data = new byte[payload];
  152.             for (int i=0; i<payload; i++)
  153.             {
  154.                 data[i]=file[i+(seqnum*payload)-payload];
  155.             }
  156.             return data;
  157.         }
  158.         catch (ArrayIndexOutOfBoundsException e)
  159.         {
  160.             byte[] data = new byte[file.length % payload];
  161.             for (int i=0; i<data.length; i++)
  162.             {
  163.                 data[i]=file[i+(seqnum*payload)-payload];
  164.             }
  165.             return data;
  166.         }
  167.     }
  168.  
  169.     /**
  170.      * This method will send the packet to the specified host
  171.      * @param targethost - who we're sending the data to
  172.      * @param payload - amount of data in bytes to send
  173.      */
  174.     private boolean sendData(String targethost, int payload)
  175.     {
  176.         try
  177.         {
  178.             data = getDataToSend(file, payload);
  179.             if (data.length == 0)
  180.             {
  181.                 return false;
  182.             }
  183.             //ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
  184.             //DataOutputStream dos = new DataOutputStream(byteArray);
  185.  
  186.             byte[] buffSend = new byte[payload];    //data to send
  187.  
  188.             //create packet
  189.             Packet packet = new Packet(data, seqnum);
  190.             //dos.write(packet.getBytes());
  191.             buffSend = packet.getBytes();
  192.  
  193.             //construct and send packet
  194.             System.out.println("Sender sending packet #" + seqnum);
  195.             DatagramPacket dp = new DatagramPacket(buffSend, buffSend.length, InetAddress.getByName(targethost), PORT_NUMBER);
  196.             sock.send(dp);
  197.            
  198.             if (data.length < payload)
  199.             {
  200.                 //final data packet has been sent
  201.                 return false;
  202.             }
  203.             //still data to send
  204.             return true;
  205.         }
  206.         catch (SocketException e)
  207.         {
  208.             System.out.println("Error sending packet: " + e.toString());
  209.             shutdown();
  210.             System.exit(0);
  211.             return false;
  212.         }
  213.         catch (Exception e)
  214.         {
  215.             System.out.println("Unable to find specified host!");
  216.             return false;
  217.         }
  218.     }
  219.  
  220.     /**
  221.      * This method receives an ACK from the receiver
  222.      */
  223.     private boolean receiveACK()
  224.     {
  225.         try
  226.         {
  227.             //get the incoming ACK
  228.             buffReceive = rcvPacket.getData();
  229.             //byte[] incData = rcvPacket.getData();
  230.  
  231.             ByteArrayInputStream incByteArray = new ByteArrayInputStream(buffReceive);
  232.             DataInputStream dis = new DataInputStream(incByteArray);
  233.  
  234.             //extract hash
  235.             byte[] hash = new byte[16];     //hash
  236.             dis.read(hash, 0, 16);
  237.             //extract sequence number
  238.             int acknum = dis.readInt();     //ack number
  239.             //reconstruct ACK
  240.             Packet ack = new Packet(acknum);
  241.  
  242.             //check ACK number
  243.             if (!(ack.compareACK(hash)))
  244.             {
  245.                 //incorrect ACK
  246.                 throw new Exception("ACK mismatch");
  247.             }
  248.             else
  249.             {
  250.                 System.out.println("Sender received ACK #" + acknum);
  251.                 if (acknum == seqnum)
  252.                 {
  253.                     seqnum++;
  254.                 }
  255.                 //correct ACK
  256.                 return true;
  257.             }
  258.         }
  259.         catch (Exception e)
  260.         {
  261.             System.out.println("Unknown error receiving ACK: " + e.toString());
  262.             return false;
  263.         }
  264.     }
  265.  
  266.     /**
  267.      * This method sends a message to the receiver to let them know there is no more data to send
  268.      * @param targethost - who we're sending the data to
  269.      * @param timeout - amount of time to wait in milliseconds before throwing a timeout exception
  270.      */
  271.     private void sendTerminator(String targethost, int timeout)
  272.     {
  273.         try
  274.         {
  275.             boolean rcvTerm = false;    //receiver terminated
  276.             while (!rcvTerm)
  277.             {
  278.                 //send terminator
  279.                 System.out.println("Sender sending terminator to receiver");
  280.                 Packet terminator = new Packet(-1);
  281.                 byte[] end = terminator.getACK();
  282.                 DatagramPacket dp = new DatagramPacket(end, end.length, InetAddress.getByName(targethost), PORT_NUMBER);
  283.                 sock.send(dp);
  284.  
  285.                 //set socket timeout
  286.                 sock.setSoTimeout(timeout);
  287.  
  288.                 //receive terminator ACK
  289.                 rcvPacket = new DatagramPacket(buffReceive, buffReceive.length);
  290.                 sock.receive(rcvPacket);
  291.  
  292.                 rcvTerm = receiveACK();
  293.             }
  294.         }
  295.         catch (Exception e)
  296.         {
  297.             System.out.println("Unknown error sending terminator: " + e.toString());
  298.         }
  299.     }
  300. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement