I've got a server which sends to its client the contents of a text file.
The 'server' package has a 'Main' (takes in port no. from cmd line args and parses it), 'Server' and a 'FileHandler' class and I think I've got them in a way (using a threadpool) so that the server is able to serve concurrently to two clients.
Now I'm trying to build a CLI with options to start & stop the server. I'm looking to implement 2 threads, where one thread will listen for the input and another for the 'accept()' call.
My attempt at it so far has been to create a new class 'Commander.java' and take in an AtomicBoolean in the constructor and then store it in the object to use as a flag for stopping the server thread.
I want the thread that is listening for the 'accept()' call to periodically check if a request has been made to stop - how can I do this with my 'Commander' class?
Including some code snippets (a.k.a. my attempt so far) for your better understanding:
class Server implements Runnable
{
Socket sock;
ExecutorService executor;
private int port ;
public Server(int p) {
port = p ;
executor = Executors.newFixedThreadPool(2);
}
public void startServer() {
ServerSocket s = new ServerSocket(port);
...
while (true)
{
Socket temp = s.accept();
sock = temp;
executor.execute(new FileHandler(sock));
// serveFile(temp) ;
}
public void run() {
startServer();
}
}
public class Main {
public static void main(String[] args) {
while(true) {
System.out.println("Main menu:\n" +
" 1 - Start server\n"+
" 2 - Stop Server\n"+
" 0 - Exit");
int in = Integer.parseInt(scanner.nextLine());
switch(in) {
case 1:
// start server
System.out.println("Starting server...");
Thread th1 = new Thread(new Server(port));
th1.start();
System.out.println("Case continuity...");
// server.startServer() ;
break;
case 2:
// stop server
System.out.println("Server stopped.\n");
break;
case 0:
// exit
System.exit(0);
break;
}
}
}
}
class FileHandler implements Runnable {
Socket socket;
public FileHandler(Socket socket) {
this.socket = socket;
}
private void serveFile() {
...code for serving file...
}
public void run() {
serveFile();
}
}
public class Commander implements Runnable
{
private AtomicBoolean bool;
public Commander(AtomicBoolean bool) {
this.bool = new AtomicBoolean(bool);
}
public boolean value() {
return bool.get();
}
Based on @Kayaman Answer:
A- At your Server class:
1- let ServerSocket
be a class member scope:
ServerSocket s = new ServerSocket(port);
2- add a method shutdown()
:
public void shutdown(){
try{
s.close();
}catch(Exception e){
e.printStacktrace();
}
}
3- add try/catch
to handle socket close (do a clean shutdown):
while (true)
{
try{
Socket temp = s.accept();
sock = temp;
executor.execute(new FileHandler(sock));
// serveFile(temp) ;
}catch(SocketException ex){
doAcleanShutdown();
}
}
B- In your Main class:
1- let Server
instance be class member scope
Server myServer = new Server(port);
2- In switch (case 1:
) use myServer
instance
case 1:
// start server
System.out.println("Starting server...");
Thread th1 = new Thread(myServer);
th1.start();
System.out.println("Case continuity...");
// server.startServer() ;
break;
3- to stop the server, case 2:
case 2:
// stop server
myServer.shutdown();
System.out.println("Server stopped.\n");
break;