package application; import debug.*; import timer.*; import link.*; import network.*; import reliability.*; import java.io.*; import java.util.*; /***************************************************************** A class to act as an application to drive the sending end of a bytestream conversation. Matches up with a BytestreamReceiverClient on the other end, and works through a ReliableSender instance to acheive communication.

You probably won't need to worry about this class, since it will be set up by the config file parser. *****************************************************************/ public class BytestreamReceiverClient implements Runnable { private ReliableReceiver receiver; private Vector uptime; private Address addr; /************************************************************ Creates a new recevier client and starts the run thread for it. Clients should not be made to share receiver instances, because it probably won't work. @param receiveImplementation the ReliableReceiver instance (which needs to be connected to a network and have an address set) through which to receive @param upPeriods a vector of TimeIntervals indicating over which time periods bandwidth should be computed. If null then bandwidth is computed continuously. @param address the address of this host. Used to name the receiving thread and for messages ************************************************************/ public BytestreamReceiverClient (ReliableReceiver receiveImplementation, Vector upPeriods, Address address) { System.out.println ("Creating new receiver"); receiver = receiveImplementation; uptime = upPeriods; addr = address; Thread sendThread = new Thread (this); Timer.global.RegisterThread (sendThread); sendThread.start (); } private static int CHUNKSIZE = 20; /************************************************************ The receiving thread. Clients should not call this: the thread is started automatically by the constructor ************************************************************/ public void run () { System.out.println ("starting new receiver"); Thread.currentThread ().setName ("Recevier application at " + addr); synchronized (Timer.global) { long oldTime = Timer.global.CurrentSimTime (); long newTime = oldTime; int linesReceived = 0; while (uptime == null || uptime.size () > 0) { if (uptime != null) { TimeInterval current = (TimeInterval) uptime.elementAt (0); if (current.start > Timer.global.CurrentSimTime ()) { Debug.println ('a', "" + Timer.global.CurrentSimTime () + ": " + addr + ": holding receive info for start at " + current.start); linesReceived = 0; oldTime = Timer.global.CurrentSimTime (); // FIX: was 0 } else if (current.end < Timer.global.CurrentSimTime ()) { System.out.println ("----------------------------------------------------"); System.out.println ("End of receive interval at " + addr + ": " + (float)((8.0 * CHUNKSIZE * linesReceived) / (newTime - oldTime)) + " Mb/sec"); System.out.println ("----------------------------------------------------"); uptime.removeElementAt (0); } } byte[] data = receiver.Receive (CHUNKSIZE); if (data.length < CHUNKSIZE) return; newTime = Timer.global.CurrentSimTime (); ++linesReceived; String s = new String (data, 0); System.out.println ("" + Timer.global.CurrentSimTime () + ": " + addr + ": '" + s + "' (" + (8 * CHUNKSIZE * linesReceived) + " bits in " + (newTime - oldTime) + " us = " + (float)((8.0 * CHUNKSIZE * linesReceived) / (newTime - oldTime)) + " Mb/sec)"); } Timer.global.UnregisterThread (Thread.currentThread ()); } } }