Java TCP 套接字块在 readLine

Java TCP socket blocks at readLine

我正在处理一个 TCP client/server 应用程序并面临客户端总是阻塞在 br.readLine() 的问题。我尝试添加一个\n,但并没有解决问题。当我只使用 read 而不是 readLine 时,char 数组也会阻塞。

客户:

BufferedReader brInput = new BufferedReader(new InputStreamReader(System.in));
String send = brInput.readLine();

Socket socket = new Socket(host, port);
        
BufferedReader brSend = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter pr = new PrintWriter(socket.getOutputStream());
pr.println(send);
pr.flush();
        
System.out.println(brSend.readLine());  // is blocking      

socket.close();

服务器:

ServerSocket serverSocket = new ServerSocket(port);
while (true) {
    Socket socket = serverSocket.accept(); // blocks until request is received

    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
        if (line.isEmpty()) break;
    }

    PrintWriter pw = new PrintWriter(socket.getOutputStream());
    pw.write("Hello world\n");
    pw.flush();

    pw.close();
    socket.close();
}

您编写的代码是这样做的:

  • 客户端写入一行,然后尝试读取一行。

  • 服务器读取多行,直到它得到一个空行或流结束。然后它写了一行。

问题是服务器正在等待客户端做它不打算做的事情:

  • 客户端不会发送空行(除非它从标准输入读取一个),

  • 客户端不会关闭流...直到它从服务器获得响应。

因此客户端在等待服务器,服务器也在等待客户端。死锁。


有多种方法可以解决这个问题。一种简单的方法是改变这个(在客户端)

    println(send);

至此

    println(send); println();

但是,这里的一个问题是您的 "protocol" 无法处理要发送空行作为数据的情况。那是因为你隐含地使用一个空行(来自客户端)来表示 "message completed".