
/* A server that accepts connections and writes back the same 
amount. It is only interested in receiving and sending as much data as 
possible. It computes the data rate for each connection.
The receiving data rate is over 50MB/s using the default connection
localhostX9876. The transmission rate has a similar value.
In the lab, between two different machines, the data rate is almost 5MB/s
in each direction concurrently. Since the conncetion rate is 100Mb/s, that 
is a 80% utilization (2*5*8 = 80).
*/

import java.net.*;
import java.io.*;

/** It writes to the client many times a BUFFER_SIZE byte buffer */
class ServerHelper extends Thread
{
    static final int BUFFER_SIZE = 1024;

    private static char[] buffer;
    // initialize with junk the buffer array we send to client
    static {
        String hexa = "0123456789ABCDEF";
        buffer = new char[BUFFER_SIZE];
        int k = 0, j = 0;
        while (k < BUFFER_SIZE) {
            buffer[k++] = hexa.charAt(j++);
            if (j == hexa.length())
                j = 0;
        }
    }

    private OutputStreamWriter writer;
    public ServerHelper(OutputStreamWriter writer) {
        this.writer = writer;
    }

    public void run() {
        char[] buffer1 = new char[BUFFER_SIZE]; // used to read
	final int numberOfTimes = 10000;
        try {
            // For numberOfTimes, write the buffer
            for (int p = 0; p < numberOfTimes; p++) {
                writer.write(buffer, 0, buffer.length);
                writer.flush();
            }  
        } catch (Exception e) {
            System.out.println("Exception in ServerHelper "
                + e.getMessage());
        } 
        System.out.println("The ServerHelper terminated");
    }
}


public class SimpleServer
{
    public final static int DEFAULT_PORT = 9876;
    private static int port = DEFAULT_PORT;

    public static void main(String[] args) {
        if (args.length >= 1)
            port = Integer.parseInt(args[0]);
        try {
            ServerSocket listener = new ServerSocket(port);
            char[] buffer = new char[ServerHelper.BUFFER_SIZE];
	    long totalCount = 0; // total number of characters received
	    long totalTime = 0; // total time spent
            while (true) {
                Socket connected = listener.accept();
                InputStreamReader reader = 
                        new InputStreamReader ( connected.getInputStream() );
                OutputStreamWriter writer = new OutputStreamWriter(
                        connected.getOutputStream() );
		Thread h = new ServerHelper(writer);
		h.start();
                long before = System.currentTimeMillis();
                long count = 0; // characters received in a connection
                int n = 0; // characters read in a read operation
                try {
                  while (true) { //until client closes connection
		    try {
		      n = reader.read(buffer, 0, buffer.length);
		    } catch (IOException e) {
                      System.out.println("server read count = " + count
			    + " n = " + n + " " + e.getMessage());
		      break;
		    }
		    if (n <= 0) break; // no more data to read
		    count += n;
                  }
                } catch (Exception e) {
                    System.out.println("Outer server count = " + count
		    + " n = " + n + " " + e.getMessage());
                } finally {
		  h.join();
		  connected.close();
		}
                long after = System.currentTimeMillis(); 
		totalCount += count;
		totalTime += (after-before);
                System.out.printf(
                    "Time = %7d milliseconds\n"
                    + "Characters = %10d\n"
		    + "DataRate = %10d bytes/second\n"
		    + "AverageDataRate = %10d bytes/second\n",
		     after-before, count, 
                     (long)((double)count*1000/(after-before)),
                     (long)((double)totalCount*1000/totalTime)
		);
            }
        } catch (Exception e) {
            System.out.println("Server terminates " + e.getMessage());
            System.exit(1);
        }
    }
}

