import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.net.ServerSocket; import java.util.*; /* Server to create socket and manage threads of client connections. */ public class Server { private final boolean DEBUG = false; private final int NUMSOCKETS = 5; //Number of socket threads to run private final int REFRATE = 10; //Refresh period of report, in seconds private final String fileName = "numbers.log"; private ServerSocket serverSocket; private SocketThread[] threads; private ThreadGroup threadGroup; private int port; private boolean active; private long refTime; private ArrayList uniqueList; //A final list of all the unique 9 digit numbers private List incomingList;//A list to hold all new numbers from socket threads private int totalUniqueCount; private int newUniqueCount; private int newDupesCount; private BufferedWriter writer; //initialize variables, open the socket. public Server(int port) { try { writer = new BufferedWriter(new FileWriter(fileName)); } catch (IOException e) { e.printStackTrace(); } totalUniqueCount = 0; newUniqueCount = 0; newDupesCount = 0; refTime = System.nanoTime(); this.port = port; active = true; threads = new SocketThread[5]; threadGroup = new ThreadGroup("socket threads"); uniqueList = new ArrayList(); incomingList = Collections.synchronizedList(new LinkedList()); //thread safe list } //Start the server, called by main public void start() { try { serverSocket = new ServerSocket(port); } catch (IOException e) { e.printStackTrace(); } //start all socket threads for (int i = 0; i < NUMSOCKETS; i++) { threads[i] = new SocketThread(threadGroup, serverSocket, incomingList); threads[i].start(); } //Loop forever while all 5 threads running. while (threadGroup.activeCount() == NUMSOCKETS) { //Update unique list and print report every refresh period if ((System.nanoTime() - refTime) / 1000000000 > REFRATE) { updateList(); displayReport(); refTime = System.nanoTime(); } } stop(); // a thread stops running, implies terminate. Stop the server updateList(); //Last update after stopping all connections. try { writer.close(); } catch (IOException e) { e.printStackTrace(); } } //Method called to stop all threads and shut down the server public void stop() { //First, Loop through all threads and tell them to release clients and self-terminate for (int i = 0; i < NUMSOCKETS; i++) { if ((threads[i] != null) && (threads[i].isAlive())) { threads[i].setTerminate(true); threads[i].setRelease(true); } } //Second, Wait for each thread to die for (int i = 0; i < NUMSOCKETS; i++) { try { //Close the server socket serverSocket.close(); //If the thread is still running now, wait for it to die if (threads[i] != null && threads[i].isAlive()) { threads[i].join(); } } catch (Exception e) { e.printStackTrace(); } } threadGroup.destroy(); //If all threads dead, group will destroy without error active = false; } //Update list of unique new numbers from the list of incoming numbers private void updateList() { int index = uniqueList.size(); int newSize = 0; newUniqueCount = 0; newDupesCount = 0; //Cannot allow other threads to modify incomingList while we are working with it. synchronized (incomingList) { uniqueList.addAll(incomingList); incomingList.clear(); } //Calculating report data newDupesCount = removeDupes(uniqueList); newSize = uniqueList.size(); newUniqueCount = newSize - index; totalUniqueCount = newSize; for (int i = index; i < uniqueList.size(); ++i) { updateFile(uniqueList.get(i)); } } //Print report to console private void displayReport() { // System.out.print("\033[H\033[2J"); //clear the console (optional) System.out.println("Received " + newUniqueCount + " unique numbers, " + newDupesCount + " duplicates. Unique total: " + totalUniqueCount); } //Write the parameter string to the log file private void updateFile(String newNum) { try { writer.write(newNum); writer.newLine(); writer.flush(); } catch (IOException e) { e.printStackTrace(); } } //Allow main program to check if server is still active. public boolean getActive() { return this.active; } //Remove duplicate entries from src list and return number of duplicates private int removeDupes(ArrayList src) { if (src == null || src.size() < 2) { return 0; } int size = src.size(); LinkedHashSet noDupes = new LinkedHashSet(src); src.clear(); src.addAll(noDupes); return size - src.size(); } }