Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

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

Posted on 2003-11-09
4
Medium Priority
?
910 Views
Last Modified: 2011-09-20
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?
0
Comment
Question by:sandman666
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
4 Comments
 

Author Comment

by:sandman666
ID: 9711007
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
 
LVL 5

Accepted Solution

by:
lwinkenb earned 1000 total points
ID: 9711368
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
 

Author Comment

by:sandman666
ID: 9718377
hey that works nicely! Didn't think it was that easy.

Thanks alot!
0
 
LVL 5

Expert Comment

by:lwinkenb
ID: 9719926
=)
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction Java can be integrated with native programs using an interface called JNI(Java Native Interface). Native programs are programs which can directly run on the processor. JNI is simply a naming and calling convention so that the JVM (Java…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
Viewers learn about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:
Suggested Courses

670 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question