import java.io.*; import java.net.*; public class SendGBN{ //constants public static byte N = 10; //the N from "Go-Back-N" public static byte MAX_SEQ_NUMBER = 20; //The maximum sequence number public static int PORT = 7609; //the receiver's port public static int DELAY = 1000; //1 second delay for timeout //the socket DatagramSocket socket; //the ip address of the receiver InetAddress ipAddress; //variables from the algorithm byte base = 1; byte nextSeqNum = 1; //needed for receiver thread volatile boolean done = false; //number of packets sent, but unacknowledged int unAckedPackets = 0; ////////////////////////////// // // other instance variables // //main program //hostname can be included on the command line //if not, assume the receiver is listening on this machine public static void main(String[] args) throws IOException{ InetAddress ipAddress = null; if(args.length > 0){ //get specified host ipAddress = InetAddress.getByName(args[0]); } else{ //use default local host ipAddress = InetAddress.getByName("localhost"); //loopback } //create a new sender SendGBN sender = new SendGBN(ipAddress); //start processing the user's data sender.processUserData(); } //constructor public SendGBN(InetAddress ip) throws IOException{ ipAddress = ip; socket = new DatagramSocket(); //create receiver thread ACKListener rcv = new ACKListener(); //start the thread rcv.start(); ///////////////////////////// // // other initialization // } //deals with getting the data from the user to send public void processUserData() throws IOException{ //create input reading mechanism BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); System.out.println("Enter some text, to end place a . on a line alone."); String line = null; while((line = in.readLine()) != null && !(line.equals("."))){ //send one packet per character for(int i = 0; i < line.length(); i++){ char c = line.charAt(i); //wait until the queue is no longer full while(unAckedPackets == N){ //we can do this because we will be running other threads //we'll give them a chance to run Thread.yield(); } sendPacket(c); } /////////////////////////////////////////// // // wait until the queue is no longer full // send an end of line character // } done = true; socket.close(); System.out.println("Done!"); } /* * The following three methods are correspond to those in the book. * They are defined as synchronized so that only one can be active * at a time from any given thread (main thread, ackListener or timer. * This prevents problems caused by multiple thread updating your * data structures at the same time. You do NOT want to have anything * in these methods that blocks the thread such as a socket.receive or * a reader.readLine, because it will prevent other threads from entering * their methods */ public synchronized void sendPacket(char c) throws IOException{ /////////////////////////////////////////// // // Turn the char c into a packet and send it off. // Remember that a character is 2 bytes. // Called from processUserData(). // // See the book // } public synchronized void receivePacket(DatagramPacket ack){ /////////////////////////////////////////// // // Process a received packet // Called from the ACKListener thread // // See the book // } public synchronized void timeOut(){ /////////////////////////////////////////// // // Process a message from the timer. // Called from the timer. // // See the book // } class ACKListener extends Thread{ public void run(){ try{ while(!done){ //listen for packet DatagramPacket ack = null; /////////////////////////////////////////// // // Get an incoming ACK packet // //process it receivePacket(ack); } } catch(IOException ioe){ //Will enter here if the thread is listening for a packet //when we quit, and that's ok. } } } }