Java socket server: how to stop the server in a client-friendy way

Hi there,

I got 3 classes, two are Threads ("MySocketServer" and "MySocketServerThread"), the other is my GUI ("MyGUI").
The GUI has 2 buttons "Start Server" and "Stop Server".
When I click "Start Server", a new MySocketServer-Thread is launched that does the following:
Create a vector with 5 "MySocketServerThread"-Threads that go to wait()-mode till they're waken up by "MySocketServer" (.accept()-method) the moment a client tries to connect.

This works finde, the gui isn't blocked because the server has thread of it's own and up to 5 sockets can be opened. (see code below).
My problem is the "Stop Server"-Button. Once I click that, I want
1. The "MySocketServer" to stop accepting new connections -> I've done that with a simple ServerSocket.close() method call.
2. a very clean disconnect, so that all 5 clients get a "goodbye"-message.

Here is my code:
MySocketServer:
public class SauSocketServer implements Runnable
{
  public static Vector serverThreads = new Vector();
  private ServerSocket serverSocket;

  private static int serverPort = 1701;
  public static int numberOfThreads = 5;
  public static int timeout = 0;
  public boolean runServer = false;
  private Thread runner;
  private boolean acceptCients = true;

  public MySocketServer(int port)
  {
    this.serverPort = port;
    this.runner = new Thread(this);
  }

  public void run()
  {
    /* create pool of new serverThreads and start them */
    for (int i = 0; i < this.numberOfThreads; ++i)
    {
      MySocketServerThread serverThread = new MySocketServerThread();
      new Thread(serverThread, "serverThread#" + i).start();
      serverThreads.addElement(serverThread);
    }

    /* create serverSocket and wait for new connections */
    try
    {
      this.serverSocket = new ServerSocket(this.serverPort);

      while (this.acceptCients)
      {
      Socket socket = this.serverSocket.accept();
      /* once a client tries to connect to the socket, assign one of the
       * threads running, described by the vector serverThreads
       */
      MySocketServerThread serverThread;

      boolean foundFreeThread = false;
      for (int i = 0; i < this.numberOfThreads; ++i)
      {
        serverThread = (MySocketServerThread) this.serverThreads.elementAt(i);
        if (!serverThread.running)
        {
          serverThread.wakeUp(socket);
          foundFreeThread = true;
          break;
        }
      }
      if (!foundFreeThread) System.out.println("DID NOT FIND FREE THREAD FOR CLIENT");
      }
    }
    catch (IOException e)
    {
      System.out.println("1. b) SocketServer returned IOException");
    }
  }

  public void startServer() throws Exception
  {
    if (!this.runner.isAlive())
    {
      this.runner.start();
    }
  }
/* here's my attempt for the stopServer-Method ... this produced very bad results */
  public void stopServer()
  {
    System.out.println("1. a) Telling SocketServer to stop accepting new clients");
    if (this.runner.isAlive())
    {
      this.acceptCients = false;
      try
      {
      this.serverSocket.close(); // using this instead of a timeout to archive faster results
      }
      catch (IOException e)
      {
      System.out.println(e);
      }

      System.out.println("1. c) Told SocketServer to stop accepting new clients");

      MySocketServerThread serverThread;

      for (int i = 0; i < this.numberOfThreads; ++i)
      {
      serverThread = (MySocketServerThread) this.serverThreads.elementAt(i);

      if (serverThread.running)
      {
        System.out.println("2. a) serverThread " + i + " is running. Telling to stop handling client");
        serverThread.keepHandlingClient = false;
      }
      else
      {
        System.out.println("serverThread " + i + " is idle.");
      }

      while (serverThread.running)
      {
        // wait for serverThread to stop running
      }
      System.out.println("3. serverThread " + i + " has stopped running and is in wait() mode now");
      serverThread.keepAlive = false;
      }
    }
  }
}

MySocketServer:

public final class MySocketServerThread implements Runnable
{
  public boolean running = false;
  public boolean keepAlive = true;
  public boolean keepHandlingClient = true;
  public Socket socket;
  public BufferedReader in;

  public MySocketServerThread()
  {
    socket = null;
  }

  public synchronized void wakeUp(Socket s)
  {
    this.socket = s;
    this.notify(); // wakes up the thread
  }

  public synchronized void run()
  {
    while (this.keepAlive)
    {
      if (this.socket == null)
      {
      try
      {
        this.wait();
      }
      catch (InterruptedException e)
      {
        continue;
      }
      }
      this.running = true;
      try
      {
      this.handleClient();
      }
      catch (Exception e)
      {
      this.running = false;
      // error handling
      }
      try
      {
      this.socket.close();
      }
      catch (IOException e)
      {
      System.out.println(e);
      }

      this.running = false;
    }
  }

  private void handleClient() throws IOException
  {
    in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
    BufferedOutputStream outStream = new BufferedOutputStream(this.socket.getOutputStream());
    PrintStream outPrint = new PrintStream(outStream);

    int line = 0;

    boolean keepListening = true;

    this.socket.setSoTimeout(MySocketServer.timeout);

    while (this.keepHandlingClient)
    {
      line = in.readLine();
      if (line == null)
      {
      this.keepHandlingClient = false;
      }
     
      outPrint.println("You said: " + line);
      outPrint.flush();
    }
    System.out.println("This is ServerThread Nr ?. My client-listening-loop has just been broken!");
  }
}

The main problem is the BufferedReader in which is blocking the while-loop so I can't simply say this.keepHandlingClient = false to stop listening on the socket.

Any ideas?
sandman666Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

sandman666Author Commented:
of course int line = 0; is not right. Replace that with String line; I've been experimenting a lot with the code before I posted it here so sorry.
0
lwinkenbCommented:
In your MySocketServerThread add a function like so:

public void closeConnection() throws IOException{
  // Send the client a goodbye message here if you want:
  socket.close();
  // clean up any resources in the thread that you need to
}

Then in your server class, instead of calling:

serverThread.keepHandlingClient = false;

call:

serverThread.closeConnection();
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
sandman666Author Commented:
hey that works nicely! Didn't think it was that easy.

Thanks alot!
0
lwinkenbCommented:
=)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.