简体   繁体   English

BufferedReader在read()处阻塞

[英]BufferedReader blocking at read()

Im trying to create a simple chat program, with a "server" and a client, now my problem is that the program blocks while reading messages from the server to the client and vice-versa. 我试图创建一个带有“服务器”和客户端的简单聊天程序,现在我的问题是该程序在从服务器读取消息到客户端时会阻塞,反之亦然。 This example features the problem with messages from Client to Server. 此示例解决了从客户端到服务器的消息问题。

Example of what I have on the server side: 我在服务器端的示例:

private Reader input;
private Writer output;

try {

        server = new ServerSocket(this.port);

        while (true) {

            Socket connection = server.accept();

            serverDisplay("We have a connection");

            input = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            output = new BufferedWriter(new OutputStreamWriter(
                    connection.getOutputStream()));

            int c;
            StringBuffer sb = new StringBuffer();

            // This is where it blocks, the input stream should return -1 at the end of the
            // stream and break the loop, but it doesnt
            while ((c = input.read()) != -1) {
                sb.append((char) c);
            }
            serverDisplay(sb.toString());
        }

    } catch (IOException e) {
        System.out.println("IO ex in the server");
    }

For sending message on the client side I have the following code: 为了在客户端发送消息,我有以下代码:

output = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));

and

private void sendMessage(String message) {
    displayMessage(message);

    try {
        output.write(message);
        output.flush();
    } catch (IOException e) {
        System.out.println("IO ex at sendMessage client");
    }

}

It reads all the characters I send (from client to server; confirmed with Sys out) but when it is supposed to read the end of the stream (-1) it hangs there . 它读取我发送的所有字符(从客户端到服务器;已通过Sys out确认),但是当应该读取流的末尾(-1)时,它将挂在那里

I have tried to print the "c" inside the while loop to see the value it returns and it simply doesn't go in the loop neither does it break it, it just hangs there. 我试图在while循环中打印“ c”以查看其返回的值,并且它根本不会进入循环,也不会中断它,它只是挂在那里。

I'm aware there are a few questions already related to this subject but I haven't found the solution to my problem in any of them. 我知道已经有一些与此主题相关的问题,但是我没有找到解决我问题的方法。

Oddly enough (at least for me) if I use : 奇怪的是(至少对我来说), 如果我使用

output = new ObjectOutputStream(connection.getOutputStream());
input = new ObjectInputStream(connection.getInputStream());

and: 和:

while ((message = (String) input.readObject()) != null)

Instead of: 代替:

input = new BufferedReader(new InputStreamReader(connection.getInputStream()));
output = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));

And: 和:

while ((c = input.read()) != -1) 

The hole thing works. 孔的东西起作用。 However this is not how I want to do it, and by reading the API's of the BufferedReader/Writer, Input/OutputStreamWriter I would think my code should work. 但是,这不是我想要的方式,通过阅读BufferedReader / Writer,Input / OutputStreamWriter的API,我认为我的代码应该可以工作。

Thank you in advance. 先感谢您。

The end of stream on the receiver side isn't reached until the sending stream (or entire socket) is closed. 在关闭发送流(或整个套接字)之前,不会到达接收器端的流的末尾。

output.close() on the send side will cause the receive side to see end of stream. 发送方的output.close()将使接收方看到流的结尾。

If you need to use the stream for multiple messages, you'll need to introduce a frame structure in to your application protocol so that receiver can determine message boundaries. 如果需要将流用于多条消息,则需要在应用程序协议中引入帧结构,以便接收方可以确定消息边界。 This can be as simple as prefixing the length of the message in bytes to each message. 这可以很简单,只需在每条消息的前缀以字节为单位的消息长度。

Since you are using a String as your entire message. 由于您使用字符串作为整个消息。 You can use DataInputStream and DataOutputStream stream decorators to frame the message for you with readUTF() and writeUTF(String) . 您可以使用DataInputStreamDataOutputStream流装饰器通过readUTF()writeUTF(String)为您构造消息。 writeUTF(String) basically frames the string by writing its length to stream before writing the string. writeUTF(String)基本上是通过在写入字符串之前将其长度写入流来构架该字符串。 readUTF() then reads this length and then knows how much data it needs to read off the stream before returning. readUTF()然后读取此长度,然后知道在返回之前需要从流中读取多少数据。

Example: 例:

Output: 输出:

DataOutputStream output = new DataOutputStream(connection.getOutputStream());

private void sendMessage(String message) {
    displayMessage(message);

    try {
        output.writeUTF(message);
        output.flush();
    } catch (IOException e) {
        System.out.println("IO ex at sendMessage client");
    }

}

Input: 输入:

DataInputStream input = new DataInputStream(connection.getInputStream());

String message = input.readUTF();

serverDispaly(message);

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

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