I am implementing a multi-threaded client-server application in java. I want to implement JDBC in this program and I want my server to retrieve data from the database whenever it is started. I will store that data in my collection instances, perform manipulations on data and when server completes execution, I need to store the data back to the database. The problem is that the server is in an infinite loop waiting for clients and I am not able to figure out how to make the server stop.
This is my server program:
import java.io.*;
import java.text.*;
import java.util.*;
import java.net.*;
public class Server
{
public static void main(String[] args) throws IOException
{
// server is listening on port 5056
ServerSocket ss = new ServerSocket(5056);
// running infinite loop for getting
// client request
while (true)
{
Socket s = null;
try {
// socket object to receive incoming client requests
s = ss.accept();
System.out.println("A new client is connected : " + s);
// obtaining input and out streams
DataInputStream dis = new DataInputStream(s.getInputStream());
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
System.out.println("Assigning new thread for this client");
// create a new thread object
Thread t = new ClientHandler(s, dis, dos);
// Invoking the start() method
t.start();
}
catch (Exception e) {
s.close();
e.printStackTrace();
}
}
}
}
// ClientHandler class
class ClientHandler extends Thread
{
DateFormat fordate = new SimpleDateFormat("yyyy/MM/dd");
DateFormat fortime = new SimpleDateFormat("hh:mm:ss");
final DataInputStream dis;
final DataOutputStream dos;
final Socket s;
// Constructor
public ClientHandler(Socket s, DataInputStream dis, DataOutputStream dos)
{
this.s = s;
this.dis = dis;
this.dos = dos;
}
#Override
public void run()
{
String received;
String toreturn;
while (true) {
try {
// Ask user what he wants
dos.writeUTF("What do you want?[Date | Time]..\n"+
"Type Exit to terminate connection.");
// receive the answer from client
received = dis.readUTF();
if(received.equals("Exit"))
{
System.out.println("Client " + this.s + " sends exit...");
System.out.println("Closing this connection.");
this.s.close();
System.out.println("Connection closed");
break;
}
// creating Date object
Date date = new Date();
// write on output stream based on the
// answer from the client
switch (received) {
case "Date" :
toreturn = fordate.format(date);
dos.writeUTF(toreturn);
break;
case "Time" :
toreturn = fortime.format(date);
dos.writeUTF(toreturn);
break;
default:
dos.writeUTF("Invalid input");
break;
}
}
catch (IOException e) {
e.printStackTrace();
}
}
try
{
// closing resources
this.dis.close();
this.dos.close();
}
catch(IOException e){
e.printStackTrace();
}
}
}
Here is my client program:
import java.io.*;
import java.net.*;
import java.util.Scanner;
// Client class
public class Client
{
public static void main(String[] args) throws IOException
{
try
{
Scanner scn = new Scanner(System.in);
// getting localhost ip
InetAddress ip = InetAddress.getByName("localhost");
// establish the connection with server port 5056
Socket s = new Socket(ip, 5056);
// obtaining input and out streams
DataInputStream dis = new DataInputStream(s.getInputStream());
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
// the following loop performs the exchange of
// information between client and client handler
while (true)
{
System.out.println(dis.readUTF());
String tosend = scn.nextLine();
dos.writeUTF(tosend);
// If client sends exit,close this connection
// and then break from the while loop
if(tosend.equals("Exit"))
{
System.out.println("Closing this connection : " + s);
s.close();
System.out.println("Connection closed");
break;
}
// printing date or time as requested by client
String received = dis.readUTF();
System.out.println(received);
}
// closing resources
scn.close();
dis.close();
dos.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}
Overview
Great question! To reiterate what was stated in the above comments, you are looking for a server-side shutdown. There are some way of handling this situation, and I can explain it with a brief example.
ExecutorServer
I will run through a modified example based off this example. Below find the server implementation.
class NetworkService implements Runnable {
private final ServerSocket serverSocket;
private final ExecutorService pool;
private final AtomicBoolean shouldExit;
public NetworkService(int port, int poolSize) throws IOException {
serverSocket = new ServerSocket(port);
pool = Executors.newFixedThreadPool(poolSize);
shouldExit = new AtomicBoolean(false); // Thread-safe boolean
}
public void run() { // run the service
try {
// While we should not exit
while(!shouldExit.get()) {
try {
pool.execute(new ClientHandler(serverSocket.accept()));
} catch (SocketException e) {
if(shouldExit.get()) break; // Poison pill has been delivered, lets stop
// Error handling
}
}
} catch (IOException ex) {
pool.shutdown();
}
// Clean up the thread pool
shutdownAndAwaitTermination();
}
}
class ClientHandler implements Runnable {
private final Socket socket;
ClientHandler (Socket socket) { this.socket = socket; }
public void run() {
...
}
...
}
Here you will modify your current Server code to intimidate this structure. You have a similar make up currently but here we have added ExecutorService.
An Executor that provides methods to manage termination and methods that can produce a Future for tracking progress of one or more asynchronous tasks.
By dispatching your ClientHandler to an ExecutorService, you are utilizing a ThreadPool. Although this comes with plenty of benefits, the most significant ones are that you have more control over your multi-threaded service, the ThreadPool will manage thread utilization, and the application efficiency will increase tremendously.
Below is how you would attempt to shutdown and terminate all remaining threads:
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
Now, the question remains how do we shutdown the server? The above code shows a improved structure, but still have the issue of blocking on a serverSocket.accept()!
Solution
There are two ideas that come to mind when thinking of this scenario; a CLI or a GUI. Both have the same semantics, and the decision is ultimately up to you. For purposes of explaining, I will refer to a CLI approach.
Poison Pill
If you implement a new Thread() that handled all incoming commands from the CLI, this thread would act as a poison pill. The idea is to deliver a poison pill to the target such that can wake up/execute and die. The thread will change the shouldExit atomic boolean to true and create a new Socket(serverSocket.getInetAddress(), serverSocket.getLocalPort()).close(); to connect to the ServerSocket and immediately close it. In the above code, the application will no longer be blocking on the serverSocket.accept(). Instead, it will enter the try catch for SocketExceptions and test if a poison pill was utilized; If it was then lets clean up, if not lets error handle.
Timeout
You could also set a timeout on the ServerSocket such that it will throw an exception each time it cannot get a connection in that time interval with myServer.setSoTimeout(2000);. This will throw an InterruptedIOException and can be handled similarly to the poison pill where the flag is changed via a CLI command and it checks if it should exit in the catch block. If it should exit, lets clean up, if not lets error handle.
You can use pattern flag with volatile boolean variable, and you should place it in 'while' - when processing would be finished, turn it to false and the server would stop.
Another way - use thread pools and wait for them to finish in the main thread of your server.
Related
In my main thread I have a while(listening) loop which calls accept() on my ServerSocket object, then starts a new client thread and adds it to a Collection when a new client is accepted.
I also have an Admin thread which I want to use to issue commands, like 'exit', which will cause all the client threads to be shut down, shut itself down, and shut down the main thread, by turning listening to false.
However, the accept() call in the while(listening) loop blocks, and there doesn't seem to be any way to interrupt it, so the while condition cannot be checked again and the program cannot exit!
Is there a better way to do this? Or some way to interrupt the blocking method?
You can call close() from another thread, and the accept() call will throw a SocketException.
Set timeout on accept(), then the call will timeout the blocking after specified time:
http://docs.oracle.com/javase/7/docs/api/java/net/SocketOptions.html#SO_TIMEOUT
Set a timeout on blocking Socket operations:
ServerSocket.accept();
SocketInputStream.read();
DatagramSocket.receive();
The option must be set prior to entering a blocking operation to take effect. If the timeout expires and the operation would continue to block, java.io.InterruptedIOException is raised. The Socket is not closed in this case.
Is calling close() on the ServerSocket an option?
http://java.sun.com/j2se/6/docs/api/java/net/ServerSocket.html#close%28%29
Closes this socket. Any thread currently blocked in accept() will throw a SocketException.
You can just create "void" socket for break serversocket.accept()
Server side
private static final byte END_WAITING = 66;
private static final byte CONNECT_REQUEST = 1;
while (true) {
Socket clientSock = serverSocket.accept();
int code = clientSock.getInputStream().read();
if (code == END_WAITING
/*&& clientSock.getInetAddress().getHostAddress().equals(myIp)*/) {
// End waiting clients code detected
break;
} else if (code == CONNECT_REQUEST) { // other action
// ...
}
}
Method for break server cycle
void acceptClients() {
try {
Socket s = new Socket(myIp, PORT);
s.getOutputStream().write(END_WAITING);
s.getOutputStream().flush();
s.close();
} catch (IOException e) {
}
}
The reason ServerSocket.close() throws an exception
is because you have an outputstream or an inputstream
attached to that socket.
You can avoid this exception safely by first closing the input and output streams.
Then try closing the ServerSocket.
Here is an example:
void closeServer() throws IOException {
try {
if (outputstream != null)
outputstream.close();
if (inputstream != null)
inputstream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
if (!serversock.isClosed())
serversock.close();
}
}
You can call this method to close any socket from anywhere without getting an exception.
Use serverSocket.setSoTimeout(timeoutInMillis).
OK, I got this working in a way that addresses the OP's question more directly.
Keep reading past the short answer for a Thread example of how I use this.
Short answer:
ServerSocket myServer;
Socket clientSocket;
try {
myServer = new ServerSocket(port)
myServer.setSoTimeout(2000);
//YOU MUST DO THIS ANYTIME TO ASSIGN new ServerSocket() to myServer‼!
clientSocket = myServer.accept();
//In this case, after 2 seconds the below interruption will be thrown
}
catch (java.io.InterruptedIOException e) {
/* This is where you handle the timeout. THIS WILL NOT stop
the running of your code unless you issue a break; so you
can do whatever you need to do here to handle whatever you
want to happen when the timeout occurs.
*/
}
Real world example:
In this example, I have a ServerSocket waiting for a connection inside a Thread. When I close the app, I want to shut down the thread (more specifically, the socket) in a clean manner before I let the app close, so I use the .setSoTimeout() on the ServerSocket then I use the interrupt that is thrown after the timeout to check and see if the parent is trying to shut down the thread. If so, then I set close the socket, then set a flag indicating that the thread is done, then I break out of the Threads loop which returns a null.
package MyServer;
import javafx.concurrent.Task;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import javafx.concurrent.Task;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
public class Server {
public Server (int port) {this.port = port;}
private boolean threadDone = false;
private boolean threadInterrupted = false;
private boolean threadRunning = false;
private ServerSocket myServer = null;
private Socket clientSocket = null;
private Thread serverThread = null;;
private int port;
private static final int SO_TIMEOUT = 5000; //5 seconds
public void startServer() {
if (!threadRunning) {
serverThread = new Thread(thisServerTask);
serverThread.setDaemon(true);
serverThread.start();
}
}
public void stopServer() {
if (threadRunning) {
threadInterrupted = true;
while (!threadDone) {
//We are just waiting for the timeout to exception happen
}
if (threadDone) {threadRunning = false;}
}
}
public boolean isRunning() {return threadRunning;}
private Task<Void> thisServerTask = new Task <Void>() {
#Override public Void call() throws InterruptedException {
threadRunning = true;
try {
myServer = new ServerSocket(port);
myServer.setSoTimeout(SO_TIMEOUT);
clientSocket = new Socket();
} catch (IOException e) {
e.printStackTrace();
}
while(true) {
try {
clientSocket = myServer.accept();
}
catch (java.io.InterruptedIOException e) {
if (threadInterrupted) {
try { clientSocket.close(); } //This is the clean exit I'm after.
catch (IOException e1) { e1.printStackTrace(); }
threadDone = true;
break;
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
};
}
Then, in my Controller class ... (I will only show relevant code, massage it into your own code as needed)
public class Controller {
Server server = null;
private static final int port = 10000;
private void stopTheServer() {
server.stopServer();
while (server.isRunning() {
//We just wait for the server service to stop.
}
}
#FXML private void initialize() {
Platform.runLater(()-> {
server = new Server(port);
server.startServer();
Stage stage = (Stage) serverStatusLabel.getScene().getWindow();
stage.setOnCloseRequest(event->stopTheServer());
});
}
}
I hope this helps someone down the road.
Another thing you can try which is cleaner, is to check a flag in the accept loop, and then when your admin thread wants to kill the thread blocking on the accept, set the flag (make it thread safe) and then make a client socket connection to the listening socket.
The accept will stop blocking and return the new socket.
You can work out some simple protocol thing telling the listening thread to exit the thread cleanly.
And then close the socket on the client side.
No exceptions, much cleaner.
You can simply pass the timeout limit (milli seconds) as a parameter while calling accept function.
eg serverSocket.accept(1000);
automatically close the request after 1 sec
I am working on a program where I have a Server and Client class, but at the moment it only handles only one client at a time.
I need the server to be able to handle multiple clients concurrently (simultaneously), using multithreading.
Here is my Server code; how can I change it to handle multiple clients concurrently?
public static void main(String[] args) throws IOException {
ServerSocket socket = new ServerSocket(8945);
Server serverInstance = new Server();
System.out.println("Server is running. Waiting for client.");
while(true) {
server.socket = s.accept();
System.out.println("Client connected");
serverInstance.run();
System.out.println("Client disconnected. Waiting for new client.");
}
}
public void run() {
try {
try {
in = new Scanner(socket.getInputStream());
out = new PrintWriter(socket.getOutputStream());
RequestHandlingMethod();
} finally {
socket.close();
}
} catch (IOException e) {
System.err.println(e);
}
}
Create a separate class that handles the client. Make it implement Runnable so that you can just start a separate Thread with it.
public class ClientHandler implements Runnable {
private final Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
public void run() {
try (Socket socket = this.socket;
Scanner in = new Scanner(socket.getInputStream();
PrintWriter out = new PrintWriter(socket.getOutputStream()) {
//todo: do whatever you need to do
} catch (IOException ex) {
ex.printStackTrace();
}
System.out.println("Client disconnected.");
}
}
Then in your server you do:
System.out.println("Waiting for new client connection");
Socket clientSocket = s.accept();
System.out.println("Client connected");
new Thread(new ClientHandler(clientSocket)).start();
If you don't want to create a lot of disposable Threads, you might want to consider using an ExecutorService with a cached thread pool (or another thread pool of your choice if you prefer).
You would just create a new ExecutorService with ExecutorService executor = ExecutorService.newCachedThreadPool() and then inside your loop you do:
System.out.println("Waiting for new client connection");
Socket clientSocket = s.accept();
System.out.println("Client connected");
executor.submit(new ClientHandler(clientSocket));
If you think you are going to have a lot of concurrent clients, you might want to look at using a non-blocking server with NIO instead. It will have 1 single event loop thread instead (doesn't block on the accept) and handles all I/O events in there, and you can have a pool of worker threads that do the client handling logic.
In my main thread I have a while(listening) loop which calls accept() on my ServerSocket object, then starts a new client thread and adds it to a Collection when a new client is accepted.
I also have an Admin thread which I want to use to issue commands, like 'exit', which will cause all the client threads to be shut down, shut itself down, and shut down the main thread, by turning listening to false.
However, the accept() call in the while(listening) loop blocks, and there doesn't seem to be any way to interrupt it, so the while condition cannot be checked again and the program cannot exit!
Is there a better way to do this? Or some way to interrupt the blocking method?
You can call close() from another thread, and the accept() call will throw a SocketException.
Set timeout on accept(), then the call will timeout the blocking after specified time:
http://docs.oracle.com/javase/7/docs/api/java/net/SocketOptions.html#SO_TIMEOUT
Set a timeout on blocking Socket operations:
ServerSocket.accept();
SocketInputStream.read();
DatagramSocket.receive();
The option must be set prior to entering a blocking operation to take effect. If the timeout expires and the operation would continue to block, java.io.InterruptedIOException is raised. The Socket is not closed in this case.
Is calling close() on the ServerSocket an option?
http://java.sun.com/j2se/6/docs/api/java/net/ServerSocket.html#close%28%29
Closes this socket. Any thread currently blocked in accept() will throw a SocketException.
You can just create "void" socket for break serversocket.accept()
Server side
private static final byte END_WAITING = 66;
private static final byte CONNECT_REQUEST = 1;
while (true) {
Socket clientSock = serverSocket.accept();
int code = clientSock.getInputStream().read();
if (code == END_WAITING
/*&& clientSock.getInetAddress().getHostAddress().equals(myIp)*/) {
// End waiting clients code detected
break;
} else if (code == CONNECT_REQUEST) { // other action
// ...
}
}
Method for break server cycle
void acceptClients() {
try {
Socket s = new Socket(myIp, PORT);
s.getOutputStream().write(END_WAITING);
s.getOutputStream().flush();
s.close();
} catch (IOException e) {
}
}
The reason ServerSocket.close() throws an exception
is because you have an outputstream or an inputstream
attached to that socket.
You can avoid this exception safely by first closing the input and output streams.
Then try closing the ServerSocket.
Here is an example:
void closeServer() throws IOException {
try {
if (outputstream != null)
outputstream.close();
if (inputstream != null)
inputstream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
if (!serversock.isClosed())
serversock.close();
}
}
You can call this method to close any socket from anywhere without getting an exception.
Use serverSocket.setSoTimeout(timeoutInMillis).
OK, I got this working in a way that addresses the OP's question more directly.
Keep reading past the short answer for a Thread example of how I use this.
Short answer:
ServerSocket myServer;
Socket clientSocket;
try {
myServer = new ServerSocket(port)
myServer.setSoTimeout(2000);
//YOU MUST DO THIS ANYTIME TO ASSIGN new ServerSocket() to myServer‼!
clientSocket = myServer.accept();
//In this case, after 2 seconds the below interruption will be thrown
}
catch (java.io.InterruptedIOException e) {
/* This is where you handle the timeout. THIS WILL NOT stop
the running of your code unless you issue a break; so you
can do whatever you need to do here to handle whatever you
want to happen when the timeout occurs.
*/
}
Real world example:
In this example, I have a ServerSocket waiting for a connection inside a Thread. When I close the app, I want to shut down the thread (more specifically, the socket) in a clean manner before I let the app close, so I use the .setSoTimeout() on the ServerSocket then I use the interrupt that is thrown after the timeout to check and see if the parent is trying to shut down the thread. If so, then I set close the socket, then set a flag indicating that the thread is done, then I break out of the Threads loop which returns a null.
package MyServer;
import javafx.concurrent.Task;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import javafx.concurrent.Task;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
public class Server {
public Server (int port) {this.port = port;}
private boolean threadDone = false;
private boolean threadInterrupted = false;
private boolean threadRunning = false;
private ServerSocket myServer = null;
private Socket clientSocket = null;
private Thread serverThread = null;;
private int port;
private static final int SO_TIMEOUT = 5000; //5 seconds
public void startServer() {
if (!threadRunning) {
serverThread = new Thread(thisServerTask);
serverThread.setDaemon(true);
serverThread.start();
}
}
public void stopServer() {
if (threadRunning) {
threadInterrupted = true;
while (!threadDone) {
//We are just waiting for the timeout to exception happen
}
if (threadDone) {threadRunning = false;}
}
}
public boolean isRunning() {return threadRunning;}
private Task<Void> thisServerTask = new Task <Void>() {
#Override public Void call() throws InterruptedException {
threadRunning = true;
try {
myServer = new ServerSocket(port);
myServer.setSoTimeout(SO_TIMEOUT);
clientSocket = new Socket();
} catch (IOException e) {
e.printStackTrace();
}
while(true) {
try {
clientSocket = myServer.accept();
}
catch (java.io.InterruptedIOException e) {
if (threadInterrupted) {
try { clientSocket.close(); } //This is the clean exit I'm after.
catch (IOException e1) { e1.printStackTrace(); }
threadDone = true;
break;
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
};
}
Then, in my Controller class ... (I will only show relevant code, massage it into your own code as needed)
public class Controller {
Server server = null;
private static final int port = 10000;
private void stopTheServer() {
server.stopServer();
while (server.isRunning() {
//We just wait for the server service to stop.
}
}
#FXML private void initialize() {
Platform.runLater(()-> {
server = new Server(port);
server.startServer();
Stage stage = (Stage) serverStatusLabel.getScene().getWindow();
stage.setOnCloseRequest(event->stopTheServer());
});
}
}
I hope this helps someone down the road.
Another thing you can try which is cleaner, is to check a flag in the accept loop, and then when your admin thread wants to kill the thread blocking on the accept, set the flag (make it thread safe) and then make a client socket connection to the listening socket.
The accept will stop blocking and return the new socket.
You can work out some simple protocol thing telling the listening thread to exit the thread cleanly.
And then close the socket on the client side.
No exceptions, much cleaner.
You can simply pass the timeout limit (milli seconds) as a parameter while calling accept function.
eg serverSocket.accept(1000);
automatically close the request after 1 sec
I'm trying to use server sockets to set up a connection between a client and a server. I'm also not using java.nio.
The problem is that I'm constantly sending a test message, and detecting whether if it is successful in sending the message (the client is still connected), if not, then the client is disconnected.
Shown here:
try
{
Scanner in = new Scanner(socket.getInputStream());
BufferedReader in_2 = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(stopThread)
{
if(in_2.ready())
{
String message = in_2.readLine();
dt = new DateTime();
PrintStream out = new PrintStream(socket.getOutputStream());
server.detect(message, dataSets, out);
dataSets.add(message);
GUI.textArea_1.append(message + "\r\n");
GUI.textArea_1.setCaretPosition(GUI.textArea_1.getDocument().getLength());
}
else
{
PrintStream out = new PrintStream(socket.getOutputStream());
out.println("Testing Connection \r\n");
if(out.checkError())
{
try
{
socket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
stopThread = false;
GUI.textArea.append(userName + " disconnected \r\n");
GUI.textArea.setCaretPosition(GUI.textArea.getDocument().getLength());
server.inputDataForm(userName, dt, dataSets);
}
Thread.sleep(3000);
}
}
The problem is that the Thread.sleep(3000) is actually interfering with getting data, since after 3 seconds, I will get a huge amount of data (because I stopped the thread for 3 seconds).
Now, what I proposed is a anonymous class in the else statement.
class runThread implements runnable
{
void run()
{
//Put the else statement here
}
}
But the stopThread = false is not a constant, which I'm trying to control.
Other threads I've searched only puts variables inside main inside the anonymous class, but I need stopThread to stop the while loop if the client is disconnected.
Does anyone have an idea?
Thanks!
Consider setting a short timeout on your socket. This will allow you to control how long your thread will block while waiting for data from the socket.
If data are not quickly available, a very specific java.net.SocketTimeoutException will be raised. You can handle this exception by checking your stopThread flag. If it is set, you can return from the method. Otherwise, the socket is still valid and you can try another read operation with timeout.
If any other exception type is thrown, your socket is probably no longer valid.
socket.setSoTimeout(20); /* 1/50th of a second. */
BufferedReader in = new BufferedReader
(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
while (!stop) {
try {
String message = in.readLine();
if (message == null)
handleEOF();
else
handleMessage(message);
} catch(SocketTimeoutException ignore) {
/* Loop back to check "stop" flag. */
continue;
} catch(IOException ex) {
handleDisconnection();
break;
}
}
By the way, if you are using Swing, remember that you can only modify graphical components from Swing's Event Dispatch Thread, and you can't tie up the EDT in long-running operations like this socket handling. You should be passing tasks from this thread to Swing's invokeLater() utility.
Why don't you make a class that implements runnable but also has the method stop();
public class MyRunner implements Runnable(){
MutableBoolean stop = false;
public void run(){...}
public void stop(){
stop = true;
}
}
I'm trying to create a server to send a message which is based on the calculation result from another class.
My question is that since the calculation result is from another class, how do I make the server pause till the result is ready, and how should I pass the result to my server class and send out the result?
public class MyServer {
ServerSocket providerSocket;
Socket connection = null;
static ObjectOutputStream out;
ObjectInputStream in;
String message;
public static String myServerSend;
BufferedReader data = new BufferedReader(data);
MyServer() {}
void run() {
try {
providerSocket = new ServerSocket(2013, 10);
System.out.println("Waiting for connection");
connection = providerSocket.accept();
out = new ObjectOutputStream(connection.getOutputStream());
out.flush();
in = new ObjectInputStream(connection.getInputStream());
do {
try {
message = (String) in.readObject();
System.out.println("server receive>" + message);
// HERE IS MY QUESTION
// myServerSend is the result from other class,
//How can I pause the server here till myServerSend is ready???????
sendMessage(myServerSend);
} catch (ClassNotFoundException classnot) {
System.err.println("Data received in unknown format");
}
} while (!message.equals("bye"));
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
//write msg into ObjectOutputStream
public static void sendMessage(String msg) {
try {
out.writeObject(msg);
out.flush();
System.out.println("server send>" + msg);
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
Use
Thread.sleep(30000); // Milli secs - 30 secs -- Put your sleep time
sendMessage(myServerSend);
Without more specific info about what you have tried and why you have discarded what you have tried, I see several options here.
Call directly the other class and wait till the result is ready. This may not be a good idea if the calculation takes too long, but if not, it's the simplest way.
You can apply polling and get the server to sleep for a certain amount of time to not exhaust resources while waiting for an answer.
Use synchronized objects and concurrency via wait and notify methods. Some useful links on this: 1 2 3
You have few options to acheive this:
1- Create a Thread for your calculation and call join to make your server wait for the thread to finish
Thread thread = new Thread() {
public void run(){
// Call your calculation class
}
}
thread.start();
thread.join(); // surround with try and catch
// or you can use to timeout if the calculation took long
// thread.join(MAX_TIME_MILLIS);
sendMessage(myServerSend);
2- Use wait/notify on a shared object between your server and calculation class
3- Use semaphore object initialized with 0 and call acquire in your server class to wait and call release after you finish your calculations, see my answer here for an example