简体   繁体   English

java.net.Socket> InputStream> BufferedReader.read(char [])阻塞线程

[英]java.net.Socket > InputStream > BufferedReader.read(char[]) blocks thread

I'm trying to use BufferedReader.read(char[]) method instead of the easier, but less versatile BufferedReader.readLine() method for receiving an answer from a Server. 我正在尝试使用BufferedReader.read(char [])方法,而不是更简单但用途更广泛的BufferedReader.readLine()方法,以从服务器接收答案。 BufferedReader is used in parallel with BufferedOutputStream and, in the code below, the read(char[]) method blocks everything, the last console output is " new buffer, waiting to read. " BufferedReader与BufferedOutputStream并行使用,在下面的代码中,read(char [])方法将阻止所有内容,最后一个控制台输出是“ 新缓冲区,等待读取”。

Client: 客户:

public class MessageSender extends Thread {
private String message;
MessageSender(String message) {
    this.message = message;
}

public void run() {
    try {
        Socket sk = new Socket("192.168.1.4", 3000);
        BufferedOutputStream bo = new BufferedOutputStream(sk.getOutputStream());
        bo.write(message.getBytes());
        bo.flush();

        char[] c = new char[100];

        BufferedReader br = new BufferedReader(new InputStreamReader(sk.getInputStream()));
        StringBuffer sb = new StringBuffer();
        System.out.println("new buffer, waiting to read.");
        int ix = 0;

        while (ix != -1) {
            ix = br.read(c);
            sb.append(new String(c));
        }

        String message = sb.toString();

        System.out.println("reply: " + message);

        sk.close();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

} }

Server: 服务器:

public class MessageReceiver extends Thread {
    public void run() {
        try {
            ServerSocket ss = new ServerSocket(3000);
            System.out.println("server socket open");
            while (true) {
                Socket sk = ss.accept();
                System.out.println("new connection");
                BufferedReader br = new BufferedReader(new InputStreamReader(sk.getInputStream()));
                String line = br.readLine();
                System.out.println("received line: " + line);
                BufferedOutputStream bo = new BufferedOutputStream(sk.getOutputStream());
                bo.write("ack".getBytes()); bo.flush(); //bo.close();
                sk.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Main: 主要:

public class Main {

    public static void main(String[] args) {
        MessageReceiver mr = new MessageReceiver();
        mr.start();
        while (true) {
            String msg = new Scanner(System.in).nextLine();
            MessageSender ms = new MessageSender(msg+"");
            ms.start();
        }
    }
}

Everything works fine as long as the BufferedReader.read is not called. 只要不调用BufferedReader.read,一切正常。 But as the code is right now, the output doesn't seem to get sent to the server. 但是由于代码是现在,输出似乎没有发送到服务器。

UPDATE 更新

As answered by @JB Nizet, the problem lies in the server script that uses readLine() and waits for either EOL character or the connection end. @JB Nizet回答,问题出在服务器脚本中,该脚本使用readLine()并等待EOL字符或连接结束。 Therefore, adding "\\n" to the message sent from the client side solved the deadlock: 因此,在客户端发送的消息中添加“ \\ n”可以解决死锁:

bo.write((message+"\n").getBytes());

When the server accepts a connection from the client, the first thing it does is: 当服务器接受来自客户端的连接时,它要做的第一件事是:

String line = br.readLine();

So, it blocks until the client sends a complete line of text. 因此,它将阻塞直到客户端发送完整的文本行。 The server only knows the line is complete if it reads an EOL character, or if the stream is closed by the client. 如果服务器读取了EOL字符,或者客户端关闭了流,则服务器仅知道该行已完成。

When the client starts, the first thing it does is 客户端启动时,它要做的第一件事是

bo.write(message.getBytes());

And message is a line of text, without any EOL. message是一行文本,没有任何终止。 Then the client does 然后客户做

ix = br.read(c);

so it waits for a response from the server, which is itself waiting for an EOL from the client. 因此它等待服务器的响应,服务器本身也在等待客户端的EOL。

You have implemented a networked deadlock. 您已经实现了网络死锁。

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

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