Solved

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

Posted on 2003-11-09
4
889 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
  • 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 250 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

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
simple java question 3 55
nextBoolean(double p) for Random class 3 40
Detect Closed Loops (circles, figure-8s, etc) in PNG Images 6 33
Problem to Alipay 10 22
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Java functions are among the best things for programmers to work with as Java sites can be very easy to read and prepare. Java especially simplifies many processes in the coding industry as it helps integrate many forms of technology and different d…
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:

776 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