读取()时BufferedReader阻塞

ped*_*mss 2 java io bufferedreader

我试图用"服务器"和客户端创建一个简单的聊天程序,现在我的问题是程序在从服务器读取消息到客户端时阻塞,反之亦然.此示例解决了从客户端到服务器的消息问题.

我在服务器端的示例:

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");
    }
Run Code Online (Sandbox Code Playgroud)

为了在客户端发送消息,我有以下代码:

output = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
Run Code Online (Sandbox Code Playgroud)

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

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

}
Run Code Online (Sandbox Code Playgroud)

它读取我发送的所有字符(从客户端到服务器;用Sys确认),但是当它应该读取流的末尾(-1)时,它会挂起.

我试图在while循环中打印"c"以查看它返回的值,它根本不会进入循环,也不会破坏它,它只是挂在那里.

我知道有一些问题已经与这个问题有关,但我没有找到解决我问题的方法.

如果我使用的话,奇怪的是(至少对我而言):

output = new ObjectOutputStream(connection.getOutputStream());
input = new ObjectInputStream(connection.getInputStream());
Run Code Online (Sandbox Code Playgroud)

和:

while ((message = (String) input.readObject()) != null)
Run Code Online (Sandbox Code Playgroud)

代替:

input = new BufferedReader(new InputStreamReader(connection.getInputStream()));
output = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
Run Code Online (Sandbox Code Playgroud)

和:

while ((c = input.read()) != -1) 
Run Code Online (Sandbox Code Playgroud)

洞的事情有效.然而,这不是我想要的方式,通过读取BufferedReader/Writer的API,输入/ OutputStreamWriter,我认为我的代码应该工作.

先感谢您.

Dev*_*Dev 5

在发送流(或整个套接字)关闭之前,不会到达接收方的流末端.

output.close() 在发送方将导致接收方看到流的结束.

如果需要将流用于多个消息,则需要在应用程序协议中引入帧结构,以便接收方可以确定消息边界.这可以简单到为每条消息添加消息长度(以字节为单位).

因为您使用String作为整个消息.您可以使用DataInputStreamDataOutputStream流与装饰帧的消息要告诉你readUTF()writeUTF(String).writeUTF(String)基本上通过在写入字符串之前将其长度写入流来构造字符串.readUTF()然后读取此长度,然后知道在返回之前需要从流中读取多少数据.

例:

输出:

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");
    }

}
Run Code Online (Sandbox Code Playgroud)

输入:

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

String message = input.readUTF();

serverDispaly(message);
Run Code Online (Sandbox Code Playgroud)