1

我正在使用 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();
    }
}
4

2 回答 2

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);
   ...
于 2012-10-17T21:25:40.480 回答
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);
    }
}

如果客户端连接您的服务器将启动一个新线程并进入循环的下一次迭代并等待下一个客户端连接。

于 2012-10-17T21:37:55.810 回答