This repository has been archived on 2025-04-28. You can view files and clone it, but cannot push or open issues or pull requests.
number-listener/Server.java
2021-01-25 13:57:29 -08:00

182 lines
5.6 KiB
Java

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<String> uniqueList; //A final list of all the unique 9 digit numbers
private List<String> 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<String>();
incomingList = Collections.synchronizedList(new LinkedList<String>()); //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<String> src) {
if (src == null || src.size() < 2) {
return 0;
}
int size = src.size();
LinkedHashSet<String> noDupes = new LinkedHashSet<String>(src);
src.clear();
src.addAll(noDupes);
return size - src.size();
}
}