sandman666
asked on
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"-Thr eads 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(s erverThrea d);
}
/* create serverSocket and wait for new connections */
try
{
this.serverSocket = new ServerSocket(this.serverPo rt);
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.element At(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.element At(i);
if (serverThread.running)
{
System.out.println("2. a) serverThread " + i + " is running. Telling to stop handling client");
serverThread.keepHandlingC lient = false;
}
else
{
System.out.println("server Thread " + 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.soc ket.getInp utStream() ));
BufferedOutputStream outStream = new BufferedOutputStream(this. socket.get OutputStre am());
PrintStream outPrint = new PrintStream(outStream);
int line = 0;
boolean keepListening = true;
this.socket.setSoTimeout(M ySocketSer ver.timeou t);
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?
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"-Thr
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(s
}
/* create serverSocket and wait for new connections */
try
{
this.serverSocket = new ServerSocket(this.serverPo
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.element
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();
}
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.element
if (serverThread.running)
{
System.out.println("2. a) serverThread " + i + " is running. Telling to stop handling client");
serverThread.keepHandlingC
}
else
{
System.out.println("server
}
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.soc
BufferedOutputStream outStream = new BufferedOutputStream(this.
PrintStream outPrint = new PrintStream(outStream);
int line = 0;
boolean keepListening = true;
this.socket.setSoTimeout(M
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?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
hey that works nicely! Didn't think it was that easy.
Thanks alot!
Thanks alot!
=)
ASKER