我正在使用Oracle的Knock Knock示例来编写服务器和客户端,当客户端连接到服务器时,它会收到一个与之交互的Knock Knock笑话。一切都很好。
我的问题是,当客户端完成并且自身与服务器断开连接时,服务器程序也会终止。如果服务器终止,我可以再次自动运行它,以便它可以接受另一个客户端的请求而无需手动重启服务器端吗?
下面是我的代码,评论显示我被困住的地方。我在vmware播放器上运行两个centos vm。
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();
}
}
答案 0 :(得分:2)
在处理一个连接后关闭serverSocket
:
serverSocket.close();
您需要保持此活动并将收到的客户端连接移交给工作线程。
在main
方法中,您将拥有:
while (serverIsActive) {
clientSocket = serverSocket.accept();
new ClientWorker(clientSocket).launch();
}
ClientWorker
将为Runnable
并处理客户端连接:
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);
...
答案 1 :(得分:2)
您可以将连接处理代码移动到一个额外的线程(让我们称之为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();
}
}
一旦某人连接到您的服务器,您就会创建一个新的KnockKnockHandler实例并启动它:
try {
clientSocket = serverSocket.accept();
KnockKnockHandler handler = new KnockKnockHandler(clientSocket);
handler.start();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
如果将其置于循环中,您的服务器将永远不会关闭(抛出异常或JVM终止;-)):
while(true) {
try {
clientSocket = serverSocket.accept();
KnockKnockHandler handler = new KnockKnockHandler(clientSocket);
handler.start();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
}
如果客户端连接您的服务器,将启动一个新线程并进入循环的下一次迭代并等待下一个客户端连接。