当前位置: 首页 > 工具软件 > readline > 使用案例 >

BufferedReader.readLine()的坑

阎承嗣
2023-12-01

今天在跟朋友讨论实现服务器和客户端一对一通信的时候,客户端给服务器发送第一条数据无异常,接着服务器给客户端回数据的时候,怎么着客户端也收不到服务器的数据,调试后发现原来是卡在服务端的readLine() 方法上了

直接上代码

客户端:

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class Client {

    public static void main(String[] args) {
        Socket socket = null;
        PrintWriter printWriter = null;
        BufferedReader bufferedReader = null;
        try {

            //创建套接字
            socket = new Socket("localhost", 9999);
            while (true) {
                // 给服务器发送数据
                System.out.println("给服务器发送数据");
                Scanner scanner = new Scanner(System.in);
                String sendInfo = scanner.nextLine();
                printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
                printWriter.println(sendInfo);
                printWriter.flush();
                if ("end".equals(sendInfo)) return;

                // 接收服务端数据
                bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String serverInfo = bufferedReader.readLine();
                if ("end".equals(serverInfo)) return;
                System.out.println("服务器:" + serverInfo);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭流
            try {
                if (null != socket) {
                    socket.close();
                }
                if (null != printWriter) {
                    printWriter.close();
                }
                if (null != bufferedReader) {
                    bufferedReader.close();
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}

服务端

package org.net;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class Server {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        BufferedReader bufferedReader = null;
        try {
            System.out.println("等待客户端的连接");
            // 创建Server套接字
            serverSocket = new ServerSocket(9999);
            //接收 客户端
            socket = serverSocket.accept();
            bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while (true) {
                // 读取客户端数据
                String clientInfo = null;
                while (null != (clientInfo = bufferedReader.readLine())) {
                    System.out.println("客户端:" + clientInfo);
                }
                if ("end".equals(clientInfo)) return;

                //给客户端发送数据
                System.out.println("给客户端发送数据");
                Scanner scanner = new Scanner(System.in);
                String sendInfo = scanner.nextLine();
                PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
                printWriter.println(sendInfo);
                printWriter.flush();
                if ("end".equals(sendInfo)) return;
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {

            // 关闭连接
            try {
                if (serverSocket != null) {
                    serverSocket.close();
                }

                if (socket != null) {
                    socket.close();
                }

                if (bufferedReader != null) {
                    bufferedReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

经过和朋友的讨论以及查资料发现,原来是对nextLine()的理解错误

我们错误的理解为:nextLine()在没有接收到客户端和读完客户端的数据时返回null

while (null != (clientInfo = bufferedReader.readLine())) {
       System.out.println("客户端:" + clientInfo);
}

其实不然

正解:

  1. readLine() 方法在没有接收到客户端的请求是一直处于阻塞状态,并没有返回null。
  2. 如果readLine()方法在没有读取到回车符时,也是一直等待读取,直到读取到回车符。
  3. 如果读到了回车符,他并没返回null,而是又重新进入阻塞状态等待数据的读取。
  4. 只有在连接关闭和发生资源错误的时候nextLine()才会返回null。
 类似资料: