当前位置: 首页 > 知识库问答 >
问题:

Java while(true)循环仅在线程内执行一次

唐阳飙
2023-03-14

我试图用Java实现一个简单的客户机-服务器应用程序。

这是代码:

客户端.java

public class Client implements Runnable {
    private String hostName;
    private int portNumber;
    private String message;

    private Socket socket;
    private PrintWriter writer;
    private BufferedReader reader;

    public Client(String hostName, int portNumber, String message) {
        this.hostName = hostName;
        this.portNumber = portNumber;
        this.message = message;
    }

    public void connect() {
        try {
            socket = new Socket(hostName, portNumber);
            writer = new PrintWriter(socket.getOutputStream(), true);
            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            writer.println(message);
        } catch (UnknownHostException e) {
            System.err.println("Could not resolve the host name '" + hostName + "'.");
        } catch (IOException e) {
            System.err.println("Could not get the I/O for the connection to '" + hostName + "'.");
        }
    }

    private void listenForMessages() {
        while (true) {
            try {
                System.out.println("In loop!");
                String line;
                while ((line = reader.readLine()) != null) {
                    System.out.println(line);
                }
            } catch (IOException e) {
                System.err.println(e.getMessage());
            }
        }
    }

    public void run() {
        connect();
        listenForMessages();
    }
}

服务器.java

public class Server implements Runnable {
    private int portNumber;
    private String message;

    private ServerSocket serverSocket;
    private Socket clientSocket;
    private PrintWriter writer;
    private BufferedReader reader;

    public Server(int portNumber, String message) {
        this.portNumber = portNumber;
        this.message = message;
    }

    private void listen() {
        try {
            serverSocket = new ServerSocket(portNumber);
        } catch (IOException e) {
            System.err.println(e.getMessage());
        }

        while (true) {
            try {
                clientSocket = serverSocket.accept();
                writer = new PrintWriter(clientSocket.getOutputStream(), true);
                reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

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

                writer.println(message);
            } catch (IOException e) {
                System.err.println(e.getMessage());
                break;
            }
        }
    }

    public void run() {
        listen();
    }
}

这是主要类:

public class Test {
    public static void main(String[] args) {
        Client client = new Client("localhost", 4444, "Hello from client!");
        Server server = new Server(4444, "Hello from server!");

        Thread serverThread = new Thread(server);
        serverThread.start();

        Thread clientThread = new Thread(client);
        clientThread.start();
    }
}

代码的逻辑很简单:客户端和服务器都在等待< code>while(true)循环中的消息。

服务器的< code>listen方法中的< code>while循环执行得很好。但是,在< code>listenForMessages方法中,循环似乎只执行一次。我只看到一个“在循环”印在屏幕上。

你能找出问题所在吗?

提前谢谢你!

共有1个答案

闻华容
2023-03-14

然而,在listenForMessages方法中,循环似乎只执行一次。我只看到屏幕上印着一个“循环”。

实际上,这并不是因为循环只执行一次,而是因为< code>reader.readLine()会让当前线程等待,直到它接收到一整行,在这里,如果您检查< code>Server的代码,它会先读取,并在一个无限循环中读取,因为< code>reader.readLine()只会在流的末尾返回< code>null,所以在这种情况下,当套接字被关闭时。

如果要在客户端和服务器之间实现某种乒乓球,只需读取然后在一侧写入,然后写入和读取,另一侧如下:

客户端代码:

public void connect() {
    try {
        socket = new Socket(hostName, portNumber);
        writer = new PrintWriter(socket.getOutputStream(), true);
        reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

    } catch (UnknownHostException e) {
        System.err.println("Could not resolve the host name '" + hostName + "'.");
    } catch (IOException e) {
        System.err.println(
            "Could not get the I/O for the connection to '" + hostName + "'."
        );
    }
}

private void listenForMessages() {
    while (true) {
        try {
            System.out.println("In loop!");
            // Write the message for the server
            writer.println(message);
            // Read the message from the server
            System.out.println(reader.readLine());
        } catch (IOException e) {
            System.err.println(e.getMessage());
        }
    }
}

< code >服务器代码:

while (true) {
    try {
        clientSocket = serverSocket.accept();
        writer = new PrintWriter(clientSocket.getOutputStream(), true);
        reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

        while (true) {
            // Read the message from the client
            System.out.println(reader.readLine());
            // Write the message for the client
            writer.println(message);
        }


    } catch (IOException e) {
        System.err.println(e.getMessage());
        break;
    }
}

输出:

In loop!
Hello from client!
Hello from server!
In loop!
Hello from client!
Hello from server!
...
 类似资料:
  • 我有一个家庭作业。。。代码如下。。。有几个问题要问。。。提前谢谢。Java初学者。。。如果这看起来很笨拙,请不要笑 有没有办法对我问的每个问题使用我的IF语句,而不必为每个问题更改字符串名称? 有没有办法创建一个方法(?)对于那些如果语句,所以我不必为我问的每一个问题写出来? 如果用户在10秒内没有输入答案,我想有一个定时器提示他们回答,我该怎么做?

  • 问题内容: 我很难弄清楚为什么while循环实际上不会循环。它运行一次并停止。 我正在尝试使其循环,以便用户能够多次转换单位。任何帮助都欢迎! 问题答案: 问题在于,当您呼叫时,它会占用该号码,但不会占用该号码之后的换行符。要解决此问题,只需在调用后放一行代码。 示例和完整说明: 假设您输入“ km”,按回车,“ 123”,按回车。从程序的角度来看,输入流为。 该代码获取值,并且使输入超出第一个。

  • 我是java的新手,我正在编写这个简短的程序,您可以在其中猜测1到10之间的数字。正确的数字存储为整数。如果您猜测较低的数字,它应该说“正确的数字较高”,如果您猜测较高,它应该说“正确的数字较低”。这是我所拥有的: 所以很明显这是行不通的,因为如果你输入一个更小的数字,它会跳到下一个数字,即使这个数字更大,它也是正确的。那么,我如何解决这个问题,让它检查两个语句呢?抱歉解释得不好。谢了。

  • 问题内容: 基本上,我正在制作一款可以更新玩家位置的游戏,它使用以下线程: 效果很好,但是如果我删除System.out.println(),它将停止运行。我不知道为什么会这样,整个班级如下: 最后说明:传入布尔值upPresses和downPressed,我唯一要关注的是: 问题答案: 像这样的循环 会完全占用CPU。它开始表现更好的原因可能是因为您为I / O每次迭代产生了数百个周期。 我建议

  • 我对python中双for循环的使用感到困惑,这是我的代码: 输出如下: 它只对外循环的第一个值执行内循环,为什么会发生这种情况?我怎样才能让它在第一个和第二个变量的所有组合上循环?

  • 问题内容: 目前,我正在做以下事情,这变得很乏味: 我猜还有其他一些可以接受的方式来处理这些东西吗? 我正在寻找的功能是按需执行一次。例如,按下某个按钮。这是一个交互式应用程序,具有许多用户控制的开关。每个开关都有一个垃圾变量,只是为了跟踪是否已运行,似乎效率很低。 问题答案: 我会在函数上使用装饰器来处理跟踪运行次数的情况。 现在将只运行一次。对其的其他调用将返回。如果希望它返回其他内容,只需在