(三)阻塞式编程BIO

1.Socket与ServerSocket

  • 如果收到客户端的请求后,accept函数会返回一个Socket对象。该对象是服务器用于和客户端通信的端点。
  • accept函数是阻塞式的,直到收到客户端的请求。

2.简单演示SocketServerSocket的基本使用

目标:客户端连接到服务器后,发送消息,服务器收到后,把消息原封不动的发回去。

  2.1服务器端

public class Server {
    public static void main(String[] args) {

        final String QUIT = "quit";
        final int DEFAULT_PORT = 8888; // 服务器端使用8888作为监听端口
        ServerSocket serverSocket = null;

        // 1.绑定监听端口
        try {
            serverSocket = new ServerSocket(DEFAULT_PORT); // 创建ServerSocket实例
            System.out.println("启动服务器,监听端口" + DEFAULT_PORT);

            while (true) {
                // 2.等待客户端连接,accept()函数是阻塞式的
                Socket socket = serverSocket.accept();
                System.out.println("客户端[" + socket.getPort() + "]已连接");

                // 3.获取IO流
                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(socket.getInputStream())  // InputStreamReader:将InputStream转换为Reader
                );
                BufferedWriter writer = new BufferedWriter(
                        new OutputStreamWriter(socket.getOutputStream())
                );

                // 4.读取客户端发送的消息
                String msg = null;
                while ((msg = reader.readLine()) != null) {  // readLine()返回分隔符前的所有信息
                    System.out.println("客户端[" + socket.getPort() + "]" + msg);
                    // 5.回复客户发送的消息
                    writer.write("服务器:" + msg + "
");
                    writer.flush(); // 防止有遗留的消息留在缓冲区

                    // 查看客户端是否退出
                    if (QUIT.equals(msg)) {
                        System.out.println("客户端[" + socket.getPort() + "]已断开连接" );
                        break;
                    }
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 6.不管是否有异常,都可安全的关闭资源
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                    System.out.println("关闭serverSocket");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

  2.2客户端

public class Client {
    public static void main(String[] args) {
        final String QUIT = "quit";
        final String DEFAULT_SERVER_HOST = "127.0.0.1";
        final int DEFAULT_SERVER_PORT = 8888;
        Socket socket = null;
        BufferedWriter writer = null;

        // 1.创建Socket
        try {
            socket = new Socket(DEFAULT_SERVER_HOST, DEFAULT_SERVER_PORT);

            // 2. 创建IO流
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(socket.getInputStream())
            );
            writer = new BufferedWriter(
                    new OutputStreamWriter(socket.getOutputStream())
            );

            // 3.等待用户输入信息
            BufferedReader consoleReader = new BufferedReader(
                    new InputStreamReader(System.in) // System.in:标准的输入流,默认从键盘输入
            );
            while (true) {
                String input = consoleReader.readLine();

                // 4.发送消息给服务器
                writer.write(input + "
"); // 加上分隔符,为了保证readLine()触发
                writer.flush();

                // 5.读取服务器返回的消息
                String msg = reader.readLine();
                System.out.println(msg);

                // 查看用户是否退出
                if (QUIT.equals(input)) {
                    break;
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭外层流的同时,内层流也会自动关闭,因此如果关闭writer,那么socket也会被关闭
            if (writer != null) {
                try {
                    writer.close();
                    System.out.println("关闭socket");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

  2.3响应结果

3. 拓展练习

原文地址:https://www.cnblogs.com/HuangYJ/p/14454093.html