import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.util.LinkedList; import java.util.List; /* The server creates SocketThread objects to accept new sockets. SocketThread must manage socket connection and properly process data. */ public class SocketThread extends Thread { private final String expression = "^[0-9]{9}$";//regex for 9 digit number private final boolean DEBUG = false; private Socket clientSocket; private ServerSocket serverSocket; private ThreadGroup threadGroup; private InputStream inputStream; private OutputStream outputStream; private BufferedReader bufferedReader; private PrintWriter printWriter; private List incomingList; private String line; //Buffer string private boolean release; //flag to release current client private boolean terminate; //flag to terminate this thread public SocketThread(ThreadGroup threadGroup, ServerSocket serverSocket, List incomingList) { super(threadGroup, ""); this.incomingList = incomingList; this.serverSocket = serverSocket; this.threadGroup = threadGroup; line = null; release = false; terminate = false; } //Methods allows the server to tell thread to finish up public void setRelease(boolean release) { this.release = release; } public void setTerminate(boolean terminate) { this.terminate = terminate; } public void run() { try { //Loop to re-open socket and listen after it is closed while ((clientSocket == null) && !terminate) { release = false; clientSocket = serverSocket.accept(); inputStream = clientSocket.getInputStream(); outputStream = clientSocket.getOutputStream(); bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); printWriter = new PrintWriter(outputStream, true); //Loop to keep reading lines from buffer while socket is connected while (!release && !terminate) { line = bufferedReader.readLine(); //If the line read is 9 digits if (line != null && (line.length() == 9)) { //Case of valid, 9 digit number if (line.matches(expression)) { //Only allow one thread to add to shared list at a time synchronized (incomingList){ incomingList.add(line); } } //Case of terminate input else if (line.equals("terminate")) { release = true; terminate = true; } //Case of invalid input else { release = true; } } //Case of invalid input else if(line != null){ release = true; } //Last, If buffer is null, wait and read again. if still null, assume client closed connection else{ sleep(500); line = bufferedReader.readLine(); if(line == null){ release = true; } } } //Release the current client if (release) { clientSocket.close(); clientSocket = null; } } } catch (SocketException e){ // Do nothing, this exception is expected when another thread causes closure of serverSocket and // this client socket is still accepting. } catch (IOException | InterruptedException e) { e.printStackTrace(); } } }