Im creating a server client program where client sends certain information to the server and get according response from the server.
For continuously listening from multiple clients I have a thread in server which continuously listens client request. whenever a request is received I start another thread and send that socket to run and start listening for other clients request.
here is the code for continuously listening
while(true){
//serverListener is a ServerSocket object
clientSocket = serverListener.accept();//Waiting for any client request
//New thread started when request is received from any client
Thread thread =new Thread(new serverThread(clientSocket), "ClientThread");
thread.start();
}
Now my problem is that how can i stop the server. I know one alternative of using a boo lean variable in while loop and then changing the value, but the problem is when where thread is in waiting to get any connection at that time changing value of the boolean variable will also not stop the server.
Is there any way to solve this problem.
Typically the serverListener (which I assume is actually a ServerSocket or something) is closed by another thread. This will generate a java.net.SocketException in accept() which will terminate the loop and the thread.
final ServerSocket serverSocket = new ServerSocket(8000);
new Thread(new Runnable() {
public void run() {
while (true) {
try {
serverSocket.accept();
} catch (IOException e) {
return;
}
}
}
}).start();
Thread.sleep(10000);
serverSocket.close();
ServerSocket#setSoTimeout() may of your interest, that will abandon accept if a timeout was reached. Be aware of catch the SocketTimeoutException.
volatile boolean finishFlag = false;
while(true){
clientSocket = serverListener.accept();//Waiting for any client request
if ( finishFlag )
break;
//New thread started when request is received from any client
Thread thread =new Thread(new serverThread(clientSocket), "ClientThread");
thread.start();
}
EDIT:
for interrupting listener, you should stop this thread from outside, and then accept( ) will throws IOException
try {
while (true) {
Socket connection = server.accept( );
try {
// any work here
connection.close( );
}
catch (IOException ex) {
// maybe the client broke the connection early.
}
finally {
// Guarantee that sockets are closed when complete.
try {
if (connection != null) connection.close( );
}
catch (IOException ex) {}
}
}
catch (IOException ex) {
System.err.println(ex);
}
Related
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.
My problem is that the ServerSocket.accept() command keeps waiting until a client has connected to it. But what I want to do is that I have to listen for a client for a few seconds. If a client connects, then I send data to the client otherwise I have to terminate the ServerSocket.
So how do I bypass the ServerSocket.accept() command when no client has connected for some time?
Call ServerSocket.close() (from another thread of course). SocketException will be thrown for any thread blocking on accept(), but if a connection has been made, then existing Socket is still fine.
A simple and naive example
ServerSocket ss = new ServerSocket(8123);
new Thread() {
#Override
public void run() {
try {
Thread.sleep(5000);
ss.close();
} catch(InterruptedException e) {
} catch(IOException e) {
}
}
}.start();
Socket s = ss.accept();
I'm creating a simple http server. I have a master thread that waits in a loop for a connection to be accepted. Once a connection is accepted, I create a new worker thread to handle the connection, passing the accepted socket as an argument. Once a connection is accepted, a new thread is created for it, however the master thread will loop again, create another socket with the same connection and create another duplicated thread.
Master thread waiting for connections.
public void run(){
while(Tester.serverStatus != "quit"){
try {
Socket clientSocket = serverSocket.accept();
new Thread(new Worker(clientSocket)).start();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
this.stop();
} catch (IOException e) {
e.printStackTrace();
}
return;
}
public void stop() throws IOException{
serverSocket.close();
return;
}
Worker thread pseudocode
public void run(){
InputStream input = clientSocket.getInputStream();
//read from stream, validate request and setup the response in a byte array
input.close();
DataOutputStream output = new DataOutputStream(clientSocket.getOutputStream());
output.write(responseByteArray);
output.flush();
output.close();
clientSocket.close();
return;
}
Any ideas as to why the accept() method isn't being blocked after the first connection is accepted? It just keeps on creating duplicate Worker threads with the same Socket.
Thanks
What you describe is not possible.
You undoubtedly have some static variables somewhere that should be instance members of Worker, such as the input and/or output streams, and/or the socket itself.
Basically I need to make a server that handles multiple devices sending/receiving information. I have to be able to send commands to the devices. The number of devices is about 40 for now but will increase to maybe 400 over time. The devises will always send information once every 40seconds-60seconds which is set on the device so it can vary, but may also send more information depending on other factors, such as a responses to commands sent to it. So I have read there is java NIO which I can use or what I have currently done is created a thread for each incoming connection. The sending is not a constant thing so it needs to happen on demand, based on users input on my jsp website. So this is where I am stuck. How do I accomplish the sending of commands from outside the program where the connection is.
This is what I currently have:
Main server class to handle connections and make threads.
try (ServerSocket serverSocket = new ServerSocket(portNumber)) {
while (listening) {
ServerThread r = new ServerThread(serverSocket.accept());
Thread thread = new Thread(r);
thread.setDaemon(true);
System.out.println(thread.getId() + "thread");
thread.start();
thread.join();
}
} catch (IOException e) {
System.err.println("Could not listen on port " + portNumber);
System.exit(-1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Then the ServerThread class:
public class ServerThread implements Runnable{
private Socket socket = null;
public AtomicBoolean isStopped=new AtomicBoolean(false);
public ServerThread(Socket socket) {
this.socket = socket;
}
public void run() {
while(!this.isStopped.get()){
try (
DataInputStream in = new DataInputStream(socket.getInputStream());
) {
ReceiveThread r = new ReceiveThread(in);
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.start();
thread.join();
socket.close();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Then the ReceiveThread handles the reading/decoding.
On demand infrequent communication is better handled via UDP maybe with re-transmission implementation if you need to make sure that data is received, alternatively you can use NIO channels to handle that.
Creating a Thread for every client if the communication is infrequent is wasteful and pointless.
In my Server application I'm trying to handle the Server which is using ServerSocket like,
Start the server and wait for connection.
Stop the server which is connected with a client.
Stop the server which is waiting for a client.
I can able to start the server and make it to wait for client inside a thread using
socket = serverSocket.accept();
What I want to do is I want manually close the socket which is waiting for connection, I have tried using,
if (thread != null) {
thread.stop();
thread = null;
}
if (socket != null) {
try {
socket.close();
socket = null;
}
catch (IOException e) {
e.printStackTrace();
}
}
After executing the above code even though the socket becomes null, when I try to connect from client to server, the connection gets established, so my question is how to interrupt the serversocket which listening for connection over here,
socket = serverSocket.accept();
I think a common way of handling this is make the accept() call time out in a loop.
So something like:
ServerSocket server = new ServerSocket();
server.setSoTimeout(1000); // 1 second, could change to whatever you like
while (running) { // running would be a member variable
try {
server.accept(); // handle the connection here
}
catch (SocketTimeoutException e) {
// You don't really need to handle this
}
}
Then, when you wanted to shut down your server, just have your code set 'running' to false and it will shut down.
I hope this makes sense!
Just close the ServerSocket, and catch the resulting SocketClosedException.
And get rid of the thread.stop(). For why, see the Javadoc.