package altbit; import java.io.*; import java.net.*; import java.util.*; /** The Channel class is used to simulate the channels between * a Sender and a Receiver in the alternating bit protocol. * The "machine" that is sending messages first connects to the * channel. Then the channel connects to the target "machine". */ public class Channel { public static final int CHANNEL_PORT = 4444; public static final int NORMAL = 0; public static final int LOSEODD = 1; public static final int LOSEEVEN = 2; private int state = 1; private int channel_port; private int behavior = NORMAL; // Sockets to receive connection private ServerSocket ss; private Socket s_in; // Socket to make connection private Socket s_out; // Object InputStreams to read and write messages to Sender and Receiver private ObjectInputStream in; private ObjectOutputStream out; /** Creates a Channel listening to the default channel port number. */ public Channel() { channel_port = CHANNEL_PORT; } /** Creates a Channel listening to the passed-in port number. */ public Channel(int port) { channel_port = port; } /** Listens and connects the "machine" that is sending messages * across this channel. */ public void accept() { try { ss = new ServerSocket(channel_port); s_in = null; s_in = ss.accept(); in = new ObjectInputStream(s_in.getInputStream()); } catch (IOException e) { System.out.println("Could not receive connection."); System.out.println(e); System.exit(0); } } /** Connects the Channel object to the target "machine" listening at the * specified location. */ public boolean connect(String host, int port) { s_out = null; try { s_out = new Socket(host, port); out = new ObjectOutputStream(s_out.getOutputStream()); } catch (UnknownHostException e) { System.out.println("Host: " + host + " unknown or unavailable."); return false; } catch (IOException e) { System.out.println("Error occurred trying to connect to " + host + " at port " + port + "."); System.out.println(e); System.exit(0); } // If it works ... System.out.println("Channel up and running!"); return true; } /** Simulates a channel with errored behavior. */ private void errorBehavior() { Object o = null; while (true) { try { switch (state) { case 1: o = in.readObject(); state = 2; break; case 2: o = in.readObject(); state = 3; break; case 3: out.writeObject(o); state = 1; break; } } catch (IOException e) { ; } catch (ClassNotFoundException e) { ; } } } public static void main(String args[]) { Channel c = null; if (args.length == 0) { c = new Channel(); } else { String s = args[0]; int c_port; try { c_port = Integer.parseInt(s); } catch (NumberFormatException e) { c_port = CHANNEL_PORT; } c = new Channel(c_port); } // set channel 1 and 2 behaviors based off command-line arguments for (int i = 1; i < args.length; i++) { if (args[i].equals("-o")) c.behavior = LOSEODD; else if (args[i].equals("-e")) c.behavior = LOSEEVEN; else { System.out.println("Usage: java Channel -[oe]"); System.out.println(" option o: channel lose every odd numbered message"); System.out.println(" option e: channel lose every even numbered message"); } } // Receive connection from sending process System.out.println("Channel listening on port " + c.channel_port); System.out.flush(); c.accept(); System.out.println("Connection received."); // Make connection to target process boolean done = false; String hostname; int port; BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); while (!done) { System.out.println("Enter target Hostname and port number:"); System.out.flush(); String s; try { s = input.readLine(); } catch (IOException e) { continue; } StringTokenizer st = new StringTokenizer(s); if (st.countTokens() != 2) { System.out.println("You must enter a hostname and port number.\n"); continue; } hostname = st.nextToken(); String p = st.nextToken(); try { port = Integer.parseInt(p); } catch (NumberFormatException e) { System.out.println("You must enter a valid port number.\n"); continue; } done = c.connect(hostname, port); } if (c.behavior == LOSEODD) { c.state = 1; c.errorBehavior(); } else if (c.behavior == LOSEEVEN) { c.state = 2; c.errorBehavior(); } else { Message m = null; while (true) { try { m = (Message) c.in.readObject(); } catch (IOException e) { continue; } catch (ClassNotFoundException e) { continue; } try { c.out.writeObject(m); } catch (IOException e) { ; } } } } }