Reputation: 18884
I am using Oracle's Knock Knock example for programming a server and client whereby when the client connects to the server it receives a Knock Knock joke to interact with. Everything is running great.
My question though is when the client is done and disconnects itself from the server the server program terminates too. How if the server terminated can I have it auto run again so that it can accept another client's request without having to manually restart the server side?
Below is my code where the comment shows where I'm stuck. I am using two centos vm's running on vmware player.
import java.net.*;
import java.io.*;
public class KnockKnockServer {
public static void main(String[] args) throws IOException {
server();
/*HERE IS WHERE I AM STUCK
* If I call server() above in my main method everything runs great.
* However, I would like to put a timer or something inside main so that
* every second it checks to see if server() is still running and if not
* then start it up again.
*/
}
public static void server() throws IOException{
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(1);
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
String inputLine, outputLine;
KnockKnockProtocol kkp = new KnockKnockProtocol();
outputLine = kkp.processInput(null);
out.println(outputLine);
while ((inputLine = in.readLine()) != null) {
outputLine = kkp.processInput(inputLine);
out.println(outputLine);
if (outputLine.equals("Bye."))
break;
}
out.close();
in.close();
clientSocket.close();
serverSocket.close();
}
}
Upvotes: 1
Views: 3505
Reputation: 1477
You could move the connection handling code to an extra thread (lets call it KnockKnockHandler):
public class KnockKnockHandler extends Thread {
private Socket socket;
public KnockKnockWorker(Socket socket) {
this.socket = socket;
}
public void run() {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
String inputLine, outputLine;
KnockKnockProtocol kkp = new KnockKnockProtocol();
outputLine = kkp.processInput(null);
out.println(outputLine);
while ((inputLine = in.readLine()) != null) {
outputLine = kkp.processInput(inputLine);
out.println(outputLine);
if (outputLine.equals("Bye."))
break;
}
out.close();
in.close();
socket.close();
}
}
Once somebody connects to your server you create a new instance of KnockKnockHandler and start it:
try {
clientSocket = serverSocket.accept();
KnockKnockHandler handler = new KnockKnockHandler(clientSocket);
handler.start();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
If you take this into a loop your server will never shut down (except an exception is thrown or the JVM is terminated ;-) ):
while(true) {
try {
clientSocket = serverSocket.accept();
KnockKnockHandler handler = new KnockKnockHandler(clientSocket);
handler.start();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
}
If a client connects your server will start a new Thread and go into the next iteration of the loop and wait for the next client to connect.
Upvotes: 2
Reputation: 159844
You close the serverSocket
after dealing with one connection:
serverSocket.close();
You need to keep this alive and hand off the received client connections to a worker thread.
In your main
method, you would have:
while (serverIsActive) {
clientSocket = serverSocket.accept();
new ClientWorker(clientSocket).launch();
}
ClientWorker
would be Runnable
and handle the client connection:
public class ClientWorker implements Runnable {
public ClientWorker(Socket clientSocket) {
this.clientSocket = clientSocket;
}
public void launch() {
new Thread(this).start();
}
@Override
public void run() {
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
...
Upvotes: 2