简体   繁体   English

BufferedReader readLine() 卡住了

[英]BufferedReader readLine() stuck

I'm writing a TCP multi Client/Server app that works in an infinite loop .我正在编写一个在无限循环中工作的 TCP 多客户端/服务器应用程序。

What happens:怎么了:

  1. Client types "COMMANDS" and expects to get available commands from server.客户端键入“命令”并期望从服务器获取可用命令。
  2. Server sends lines to client.服务器向客户端发送线路。
  3. Client reads server input line-by-line and is stuck after the last one is written .客户端逐行读取服务器输入,并在最后一个写入后卡住

Expected result:预期结果:

  1. Client is prompted for keyboard input.提示客户进行键盘输入。
  2. Input is written to server.输入被写入服务器。
  3. Server sends back text.服务器发回文本。
  4. Client reads server input line-by-line.客户端逐行读取服务器输入。
  5. End of loop.循环结束。 user types commands > server responds > user gets to type commands again用户输入命令 > 服务器响应 > 用户再次输入命令

I know that BufferedReader would stop reading lines once I close the socket.我知道一旦我关闭套接字, BufferedReader就会停止读取行。 However, that's not what we want since it has to work infinitely.然而,这不是我们想要的,因为它必须无限工作。

How do I exit the loop ?如何退出循环

Client method:客户端方法:

public class Client {
    private final Socket clientSocket;
    private final BufferedReader clientInput;
    private final PrintWriter clientOutput;
    private final BufferedReader keyboardInput;

    public Client() throws IOException {
        this.clientSocket = new Socket(InetAddress.getLocalHost(), 13370);
        this.clientInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        this.clientOutput = new PrintWriter(clientSocket.getOutputStream(), true);
        this.keyboardInput = new BufferedReader(new InputStreamReader(System.in));
    }

    public static void main(String[] args) throws IOException {
        Client client = new Client();
        client.init();
    }

    private void init() {
        try {
            while (true) {
                System.out.print("> ");
                String args = keyboardInput.readLine().trim().replaceAll("\\s+", " ");
                clientOutput.println(args.toUpperCase());

// the loops doesn't seem to stop after reading all input lines
                String line;
                while ((line = clientInput.readLine()) != null) {
                    System.out.println(line);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class ClientHandler implements Runnable {
    private final int id;
    private final Socket clientSocket;

    private final PrintWriter serverOutput;
    private final BufferedReader serverInput;

//  private final ClientFiles clientFiles;

    public int getId() {
        return id;
    }

    public ClientHandler(int id, Socket clientSocket) throws IOException {
        this.id = id;
        this.clientSocket = clientSocket;
        this.serverInput = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
        this.serverOutput = new PrintWriter(this.clientSocket.getOutputStream(), true);
//      this.clientFiles = new ClientFiles(id, clientSocket);
    }

    @Override
    public void run() {
        try {
            String command;
            while ((command = serverInput.readLine()) != null) {
                executeCommand(command.split(" "));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            closeConnection();
            removeFromHosts();
        }
    }

    private void executeCommand(String[] input) throws IOException {
        String command = input[0];
//      String option = input[1];

        switch (command) {
            case "COMMANDS": {
                getCommands();
                break;
            }
//          case "LIST_LOCAL": {
//              listFiles();
//              break;
//          }
//          case "LIST_FILES": {
//              listFiles(option);
//          }
//          case "PULL": {
//              pull(clientSocket, option);
//          }
//          case "PUSH": {
//              push(clientSocket, option);
//          }
            case "DISCONNECT": {
                closeConnection();
                break;
            }
            default: {
                write("Invalid command.");
                getCommands();
                break;
            }
        }
    }

    private String read() throws IOException {
        return serverInput.readLine();
    }

    private void write(String message) {
        serverOutput.println(message);
    }

    private void getCommands() {
        write("AVAILABLE COMMANDS:");
        write("\tCOMMANDS");
        write("\t\tlists available commands");
        write("\tLIST_HOSTS");
        write("\t\tlists hosts connected to server");
        write("\tLIST_FILES");
        write("\t\tlists files from all hosts connected server");
        write("\tLIST_LOCAL");
        write("\t\tlists local files");
        write("\tLIST_FILES [HOSTS]...");
        write("\t\tlists files from provided hosts connected server");
        write("\tPULL [HOST] [FILE]");
        write("\t\tdownloads file from host");
        write("\tPUSH [HOST] [FILE]");
        write("\t\tuploads file to host");
        write("\tDISCONNECT");
        write("\t\tdisconnects client from server");

    }

    private void closeConnection() {
        try {
            serverInput.close();
            serverOutput.close();
            clientSocket.close();
            removeFromHosts();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void removeFromHosts() {
        Server.getClients().remove(this);
    }
}

Server just accepts new clients and starts new threads.服务器只接受新客户端并启动新线程。

public class Server {
    private static final AtomicInteger count = new AtomicInteger(1);
    private static final ArrayList<ClientHandler> clients = new ArrayList<>();

    public static void main(String[] args) {
        Server.init();
    }

    public static void init() {
        System.out.println("Opening server socket...");
        try (
            ServerSocket serverSocket = new ServerSocket(13370)
        ) {
            System.out.println("Server socket opened at port: " + serverSocket.getLocalPort());
            while (true) {
                System.out.println("Waiting for client connection...");
                Socket clientSocket = serverSocket.accept();
                System.out.println("Client connected.");
                ClientHandler client = new ClientHandler(count.getAndIncrement(), clientSocket);
                clients.add(client);
                System.out.println(clients);
                new Thread(client, "client-" + client.getId()).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static ArrayList<ClientHandler> getClients() {
        return clients;
    }
}

your client is waiting for more lines.您的客户正在等待更多线路。 In your code在您的代码中

   while ((line = clientInput.readLine()) != null) {
       System.out.println(line);
   }

clientInput.readLine() will never return null if server does not close the connection.如果服务器没有关闭连接,clientInput.readLine() 将永远不会返回 null。 The execution stops waiting more data.执行停止等待更多数据。

I suggest to implements a solution like insert an empty line or a special char to signal the client that the response to the command is finished.我建议实施一个解决方案,例如插入一个空行或一个特殊字符来向客户端发出对命令的响应已完成的信号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM