while 循环仅在第一个循环处停止,然后无限期地继续 运行

while loop only stops at first loop then continues to run indefinitely

此练习程序的目标只是让客户端不断发送用户通过键入和按回车键输入的消息字符串,并将其打印到控制台。第一次,Server.java 中的 String messageFromClient = in.readLine(); 似乎阻塞了(调试器不会让我退出)。然而,在向它发送 "hello" 之类的消息后,它会继续运行而不会再阻塞。

我已经搜索了几个小时,但我想我只是没有找到合适的解决方案。

这个 link Java InputStream blocking read 可能是我发现的可能对我有帮助的最接近的东西。

Client.java

import java.io.*;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.*;
import java.net.InetAddress;
import java.util.Scanner;

public class Client {
    static Socket connectionToServer;
    public static void main(String[] args) {
        try{
            connectionToServer = new Socket("192.168.1.66", 6969);
            InetAddress inetAddress = connectionToServer.getInetAddress();
            System.out.print(
                    "Connection successful" +
                    "Connected to " + inetAddress.getHostAddress() +
                    "at " + inetAddress.getHostName() + "\n"
            );

            while(true) {
                String input = System.console().readLine();
                OutputStreamWriter dOut = new OutputStreamWriter(connectionToServer.getOutputStream());
                dOut.write(input, 0, input.length());
                //dOut.flush();
                dOut.close();
            }

        } catch (IOException exception){
            System.out.print("Failed to create socket");
        }

    }
}

Server.java

import java.io.*;
import java.net.*;

public class Server {
    public static void main(String[] args) {
        ServerSocket serverSocket;
        try {
            serverSocket = new ServerSocket(6969);
            System.out.print("Server is up and running \n");
        } catch (IOException exception){
            serverSocket = null;
            System.out.print("Cannot create ServerSocket");
        }

        while (true){
            try {
                System.out.print("Waiting from client.");
                Socket socket = serverSocket.accept();
                Thread newClientSocket = new Thread(new ServerThread(socket));
                newClientSocket.start();
                System.out.print("New thread created");
            } catch (IOException exception){
                System.out.print("Failed to create socket");
            }
        }
    }
}
////////////////////////////////////////////////////////////
class ServerThread implements Runnable{
    private Socket socket;
    //constructor
    ServerThread(Socket socket){
        System.out.print("I am a new thread");
        this.socket = socket;
    }

    public void run(){
        while(true){
            try{
                System.out.print("Waiting for input.");
                InputStreamReader inputStreamReader = new InputStreamReader(socket.getInputStream());
                BufferedReader in = new BufferedReader(inputStreamReader);
                String messageFromClient = in.readLine();
                System.out.print(messageFromClient);
            } catch (IOException exception) {
                System.out.print(exception);
                break;
            }
        }
    }
}

Console.readLine() 不包括终止符。 BufferedReader.readLine() 阻塞,直到它得到一个终止换行符

改变这个:

String input = System.console().readLine();

为此:

String input = System.console().readLine() + System.lineSeparator();

您不应该为每个循环迭代构造一个新的 BufferedReader,因为 BufferedReader 将尝试完全填充其缓冲区并可能读取到第一行末尾以外的内容 - 并且该数据将会丢失,因为您在仅读取第一行后构建 new BufferedReader

将 BufferedReader 的构造移出循环,这应该对您有所帮助。另外,请确保在完成后关闭套接字。

public void run() {
    try {
        try {
            InputStreamReader inputStreamReader = new InputStreamReader(socket.getInputStream());
            BufferedReader in = new BufferedReader(inputStreamReader);
            while (true) {
                System.out.print("Waiting for input.");
                String messageFromClient = in.readLine();
                System.out.print(messageFromClient);
            }
        } finally {
            socket.close();
        }
    } catch (IOException exception) {
        System.out.print(exception);
        // TODO: handle exception
    }
}

在发送方,你不应该为每一行关闭socket的OutputStream,因为一旦你关闭它,你就不能再使用它了。并且您应该在字符串之后向服务器发送换行符,因为 Console.readLine() 方法不将其包含在其 return 值中。

        OutputStreamWriter dOut = new OutputStreamWriter(connectionToServer.getOutputStream());
        while(true) {
            String input = System.console().readLine() + "\n";
            dOut.write(input, 0, input.length());
        }
        dOut.close();