BIO/NIO/AIO

BIO/NIO/AIO

1.java的I/O演进之路

1.1 I/O的模型说明

  • I/O模型: 也就是说用什么样的通道或者通信模式和架构进行数据的传输和接收,很大程度上解决了程序通信的性能,java共支持三种网络编程I/O模型:BIO/NIO/AIO

1.2 I/O模型

BIO

image-20220529091938558

NIO

image-20220529092107233

AIO

image-20220529092305679

1.3 BIO/NIO/AIO使用场景

  • BIO : 连接数目比较小且固定的架构,因为这种方法的服务器资源要求比较高,并发局限于应用中
  • NIO : 连接数目比较多且连接比较短的架构,比如聊天室,弹幕系统
  • AIO : 连接数目比较多且连接比较长的架构,比如相册服务器

2.BIO

2.1 BIO的介绍

image-20220529093649695

2.2 BIO工作机制

image-20220529093722807

  • 实现客户端和服务器多发多收

    public class Server {
        public static void main(String[] args) {
            try {
                // 定义socket对象对服务端端口注册
                ServerSocket socket = new ServerSocket(9999);
                // 监听客户端socket连接请求
                Socket accept = socket.accept();
                // 从socket管道中得到字节输入流
                InputStream is = accept.getInputStream();
                // 包装成缓冲字符输入流
                BufferedReader bis = new BufferedReader(new InputStreamReader(is));
                String message;
                while ((message = bis.readLine()) != null) {
                    System.out.println(message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    public class Client {
        public static void main(String[] args) throws IOException {
            // 创建socket对象请求服务端的连接
            Socket socket = new Socket("localhost", 9999);
            // 从socket中获取一个字节输入流
            OutputStream os = socket.getOutputStream();
            // 把字节输入流包装成打印流
            PrintStream ps = new PrintStream(os);
            Scanner sc = new Scanner(System.in);
            while (true) {
                System.out.println("请输入");
                ps.println(sc.nextLine());
                ps.flush();
            }
        }
    }
    

2.3 BIO模式下接收多个客户端

image-20220529103921527

public class Server {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(3);
        try {
            // 定义socket对象对服务端端口注册
            ServerSocket socket = new ServerSocket(9999);
            // 定义死循环 监听客户端socket连接请求
            while (true) {
                Socket accept = socket.accept();
                pool.execute(() -> {
                    try {
                        // 从socket管道中得到字节输入流
                        InputStream is = accept.getInputStream();
                        // 包装成缓冲字符输入流
                        BufferedReader bis = new BufferedReader(new InputStreamReader(is));

                        String message;
                        while ((message = bis.readLine()) != null) {
                            System.out.println(message);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

image-20220529105230181

2.4 BIO实现文件上传

public class Client {
    public static void main(String[] args) {
        try (
                // jdk1.7以后资源释放的一种方式
                InputStream is = new FileInputStream("/Users/liubo/typora/images/image-20220518194133028.png")
        ) {
            // 请求与服务端socket连接
            Socket socket = new Socket("localhost", 8888);
            // 把字节输入流包装成数据输入流
            DataOutputStream ds = new DataOutputStream(socket.getOutputStream());
            // 先发送上传文件后缀给服务端
            ds.writeUTF(".png");
            // 把文件数据发送服务端
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) > 0) {
                ds.write(buffer);
            }
            ds.flush();
            socket.shutdownOutput(); // 通知服务端数据发送完成
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
@Slf4j(topic = "c.tes")
public class Server {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(3);
        try {
            // 定义socket对象对服务端端口注册
            ServerSocket socket = new ServerSocket(8888);
            while (true) {
                Socket accept = socket.accept();
                pool.execute(() -> {
                    try {
                        // 得到数据输入流获取客户端发来的数据
                        DataInputStream dos = new DataInputStream(accept.getInputStream());
                        // 读取客户端发来的文件类型
                        String fileType = dos.readUTF();
                        log.debug("服务器接收到文件文件类型为:{}", fileType);
                        // 定义一个字节输出管道将读取的数据写出去
                        OutputStream os = new FileOutputStream("/Users/liubo/a/" + UUID.randomUUID() + fileType);
                        // 把文件数据发送服务端
                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = dos.read(buffer)) > 0) {
                            os.write(buffer);
                        }
                        os.close();
                        log.debug("服务端接收文件保存成功");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.NIO

3.1 NIO的介绍

在这里插入图片描述

3.2 NIO和BIO比较

image-20220529144150726

3.2 NIO的三大核心

image-20220529150828225
在这里插入图片描述

image-20220529151149439

3.3 NIO Buffer介绍

缓冲区

image-20220529151425184

Buffer类及其子类

image-20220529151541561

缓冲区的基本属性

image-20220529151845660

buffer常见api

image-20220529152301979

缓冲区数据操作

image-20220529152440938

  • 使用buffer读写数据一般的4个步骤
    • 写入数据到buffer
    • 调用filp方法切换到读模式
    • 从buffer中读取数据
    • 调用buffer.clear清除缓冲区
直接与非直接内存

image-20220529160414039

image-20220529160739785

3.4 NIO Channel

通道channel概述

image-20220529161102546

常见chanel实现类

image-20220529161145790

FileChannel类

image-20220529161744081

// 写数据到文件
public class Test2 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("1.txt");
        FileChannel channel = fos.getChannel();

        ByteBuffer buffer = ByteBuffer.allocate(1024);
        String name = "ha666";
        buffer.put(name.getBytes());

        buffer.flip();
        channel.write(buffer);
        channel.close();
    }
}
// 读取文件中数据
public class Test3 {
    public static void main(String[] args) throws IOException {
        FileInputStream fos = new FileInputStream("1.txt");
        FileChannel channel = fos.getChannel();

        ByteBuffer buffer = ByteBuffer.allocate(1024);
        channel.read(buffer);
        buffer.flip();
        String value = new String(buffer.array(), 0, buffer.remaining());
        System.out.println(value);
    }
}

3.5 NIO selector

选择器selector概述

image-20220529171721014

image-20220529171853325

selector的应用

image-20220529172114106

image-20220529172124929

3.6 NIO非阻塞网络通信原理分析

服务端流程

image-20220529172407511

image-20220529173217633

客户端流程

image-20220529173242513

image-20220529173310365

5.AIO

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值