Server folosind web sockets, modificat folosind o coada de joburi si un pool de thread-uri

Includem aici doua seturi de exemple:
WebServer si
ThreadPool

Pentru WebServer:
Sursele sunt:
- Handler.java
- WebServer.java
- TestClientWebServer.java
Dupa ce compilati WebServer.java si TestClientWebServer.java,
> Porniti mai intai programul WebServer
> Porniti dupa aceea programul TestClientWebServer

Pentru ThreadPool
Sursele sunt:
- JobQueueModel.java
- JobQueue.java
- ThreadPool.java


Se observa ca, pentru fiecare conexiune accesata, WebServer va creea un nou thread pe care se apeleaza
metoda process a lui Handler. Pentru a economisi resursele, preferam sa folosim un numar limitat de
thread-uri, pe care sa le initializam fie la inceput, fie pe masura ce apar job-uri.Pentru aceasta vom
folosi un pool de thread-uri, implementat ca (exemplu minimal) in ThreadPool.ThreadPool lucreaza impreuna
cu JobQueueModel (clasa abstracta); o implementare (nu neaparat corecta) este sugerata in JobQueue


WebServer, modificat in asa fel incat sa foloseasca un pool de thread-uri si o coada de job-uri, va functiona la
fel ca in implementarea curenta (cea experimentata de dumneavoastra la laborator).
TestWebClient poate ramane neschimbat.
Va trebui sa modificati:
- Handler;
- JobQueueModel;
- ThreadPool;
- WebServer
in asa fel incat:
- WebServer sa initializeze un pool de thread-uri in locul thread-urilor pe care se proceseaza request-ul de la TestWebClient acum;
- Pentru fiecare noua conexiune  client acceptata de server se adauga un job in coada de joburi (folosind put());
- Oricare din thread-urile libere din pool-ul de thread-uri va lua urmatorul job din coada (folosind get() );

Tema de casa trebuie predata la 4 saptamani de la prezentarea ei.
Punctaj total tema de casa: 100 de puncte.
10p - puncte din oficiu;
70p - modificare WebServer, jobQueue, Handler, ThreadPool pentru a folosi un pool de thread-uri
20p - modificare program pentru a raporta thread-ul care opereaza un anume job.

Mai jos aveti sursele oferite ca punct de pornire (exemple folosite la curs si laborator)


File: Handler.java
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

public class Handler {

	void process(Socket s) {
		DataInputStream  in = null;
		DataOutputStream out = null;
		try {
			in = new DataInputStream(s.getInputStream());
			out = new DataOutputStream(s.getOutputStream());
			int request = in.readInt();
			System.out.println("[SERVER HANDLER]: read from input stream: " + request);
			int result = -request;
			out.writeInt(result);
			System.out.println("[SERVER HANDLER]: write to output stream: " + result);

		}
		catch (IOException ex) {}
		finally {
			try { if (in != null)  in.close();
			} catch(IOException ignore) {};
			try { if (out != null) out.close();
			} catch(IOException ignore) {};
			try { s.close();
			} catch(IOException ignore) {System.out.println("[SERVER HANDLER] Close port: Error closing port");};
		}
	}
}
File: WebServer.java
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class WebServer implements Runnable {
	static final int PORT = 1040;
	final int TIMEOUT = 30000;
	Handler handler = new Handler();
	ServerSocket socket = null;

	public void run() {
		try {
			socket = new ServerSocket(PORT);
			socket.setSoTimeout(TIMEOUT);
			System.out.println("[SERVER]Socket: " + socket.getLocalPort() + " " + socket.getSoTimeout());
			System.out.println("[SERVER] Web server started and waiting for requests ...");
			while(true){
				final Socket connection = socket.accept();
				new Thread(new Runnable() {
					public void run() {
						System.out.println("[SERVER] N waiting for requests ...");
						handler.process(connection);
					}
				}).start();
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}
	public static void main (String args[]) throws IOException{
		WebServer webServer = new WebServer();
		webServer.run();
	}
}

File: TestClientWebServer.java
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;


public class TestClientWebServer {

	static Socket socket = null;
	static DataInputStream  in = null;
	static DataOutputStream out = null;
	static int request = -1;
	static int response = -1;
	static final int PORT = 1040;
	static final int REQ = 1024;

	public static void main (String args[]) throws IOException {
		request = REQ;
		for(int i = 0; i < 3; i++) {
			socket = new Socket("localhost",PORT);
			try {
				in = new DataInputStream(socket.getInputStream());
				out = new DataOutputStream(socket.getOutputStream());
				out.writeInt(request);
				System.out.println("[CLIENT]: wrote to the output stream: " + request);
				response = in.readInt();
				System.out.println("[CLIENT]: read from the input stream: " + response);
				request = response * (int)(10 * Math.random());
			}
			catch (IOException ex) {}
			finally {
				try { if (in != null)  in.close();
				} catch(IOException ignore) {};
				try { if (out != null) out.close();
				} catch(IOException ignore) {};
				try { socket.close();
				} catch(IOException ignore) {System.out.println("[SERVER HANDLER] Close port: Error closing port");};
			}
		}


	}

}
File: JobQueueModel.java
public abstract class JobQueueModel {
	abstract void put(Runnable r) throws InterruptedException;
	abstract Runnable get() throws InterruptedException;
}


File: JobQueue.java
import java.util.Stack;


public class JobQueue extends JobQueueModel {

	Stack jobQueue = new Stack();
	final static int NO_ITEMS = 10;

	@Override
	void put(Runnable r) throws InterruptedException {
		jobQueue.push(r);
	}

	@Override
	Runnable get() throws InterruptedException {
		if (!jobQueue.isEmpty())
			return jobQueue.pop();
		else
			return null;
	}

}
File: ThreadPool.java
interface Executor {
	void execute(Runnable r);
}
public class ThreadPool implements Executor {
	protected final JobQueueModel  jobQueue;
	public void execute(Runnable r) {
		try {
			jobQueue.put(r);
		}
		catch(InterruptedException ie) {
			//postpone response
			Thread.currentThread().interrupt();
		}
	}
	public ThreadPool(JobQueueModel queue, int nWorkers) {
		jobQueue = queue;
		for(int i = 0; i < nWorkers; i++) {
			activation();
		}
	}

	protected void activation() {
		Runnable rx = new Runnable() {
			public void run() {
				try {
					while (true) {
						Runnable r = (Runnable) (jobQueue.get());
						r.run();
					}
				}
				catch(InterruptedException ie) {} // ready
			}
		};
		new Thread(rx).start();
	}

	public static void main (String args[]) {
		JobQueue jobQueue = new JobQueue();

		final  int NO_OF_THREADS = 2;
		new ThreadPool(jobQueue,NO_OF_THREADS);

	}
}