NIO

一 缓冲区
除了boolean类型之外的基本数据类型都有

intbuffer
shortbuffer
longbuffer
doublebuffer
floatbuffer
charbuffer
bytebuffer

在这里插入图片描述

四个关键属性
在这里插入图片描述

在这里插入图片描述
mark = -1 : 对position就进行标记,使用reset()方法可以返回,相当于存档和取档
position = 0 : 相当于下标
limit : 界限 ,有数据的界限,limit之后不能进行存取操作
capacity : 容量 ,不可变

方法
在这里插入图片描述

在这里插入图片描述

直接缓冲区: 给定一个直接字节缓冲区,Java虚拟机将尽力在其上直接执行本地I / O操作(开辟物理空间),它将尝试避免在每次调用其中一个底层操作系统的本机I / O操作之前(或之后)将缓冲区的内容复制到(或从)中间缓冲区

非直接缓冲区:在每次调用其中一个底层操作系统的本机I / O操作之前(或之后)将缓冲区的内容复制到(或从)中间缓冲区(开辟内存空间)

在这里插入图片描述

在这里插入图片描述
直接缓冲区(内存映射文件)

    @Test  //内存映射文件,直接缓冲区
    public void test2() throws Exception {
        FileChannel in = FileChannel.open(Paths.get("hello.txt"), StandardOpenOption.READ);
        FileChannel out = FileChannel.open(Paths.get("hello2.txt"), StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW);

        //内存映射文件
        MappedByteBuffer inbuf = in.map(FileChannel.MapMode.READ_ONLY, 0, in.size());
        MappedByteBuffer outbuf = out.map(FileChannel.MapMode.READ_WRITE, 0, in.size());


        // 直接对缓冲区进行操作
        byte[] bytes = new byte[inbuf.limit()];

        inbuf.get(bytes);
        outbuf.put(bytes);

        in.close();
        out.close();

    }

在这里插入图片描述

二 通道
2.1 通道(Channel):源节点和目标节点的连接

特点: 通道本身不存取数据,只具备数据缓冲区传输功能,需要与缓冲区连用

2.2 通道的主要实现类

FileChannel

ServerSocketChannel
SocketChannel

DatagramChannel

2.3 获取通道的主要方法

1 FileInputStream,FileOutputStream,RandomAccessFile
2 Socket , ServerSocket , DataGramSocket
可以通过getChannel()方法获取对应通道

在这里插入图片描述

三 通道传输

    @Test //   通道之间的传输
    public void test3() throws IOException {
        FileChannel in = FileChannel.open(Paths.get("hello.txt"), StandardOpenOption.READ);
        FileChannel out = FileChannel.open(Paths.get("hello3.txt"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);

        in.transferTo(0, in.size(), out);
        // out.transferFrom(out,0,in.size());

        out.close();
        in.close();

    }

四 分散与聚集
分散读取 :将通道中的数据分散到多个缓冲区中
聚集写入 :将多个缓冲区中的数据聚集到通道中


    @Test  // 分散读取 聚集写入
    public void test4() throws IOException {
        RandomAccessFile raf = new RandomAccessFile("hello.txt", "rw");

        // 通道
        FileChannel channel = raf.getChannel();

        // 非直接缓冲区
        ByteBuffer b1 = ByteBuffer.allocate(100);
        ByteBuffer b2 = ByteBuffer.allocate(1024);
        ByteBuffer[] bfs = {b1, b2};

        // 分散读取
        channel.read(bfs);

        for (ByteBuffer bs : bfs) {
            bs.flip();  //  转换模式
        }

        for (int i = 0; i < bfs.length; i++) {
            System.out.println(new String(bfs[i].array(), 0, bfs[i].limit()));
        }


        // 聚集写入

        RandomAccessFile raf2 = new RandomAccessFile("hello5.txt", "rw");

        FileChannel channel1 = raf2.getChannel();

        channel1.write(bfs);

        raf.close();
        raf2.close();

    }

五 网络通信(NIO)

在这里插入图片描述
三个核心
1 通道(Channel)

在这里插入图片描述

2 缓冲区(Buffer): 用于数据法存取
3 选择器(Selector):是 SelectableChannel的多路复用器,用于监控 SelectableChannel 的IO 状况

TCP
1 阻塞式

服务端


    @Test
    public void blockserver() throws IOException {
        ServerSocketChannel sChannel = ServerSocketChannel.open();
        sChannel.bind(new InetSocketAddress(9898));
        SocketChannel inchannel = sChannel.accept();//  接收服务端请求

        ByteBuffer buf = ByteBuffer.allocate(1024);

        FileChannel outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
        int len;

        while ((len = inchannel.read(buf)) != -1) {
            buf.flip();
            outChannel.write(buf);
            buf.clear();
        }
        inchannel.shutdownInput();

        buf.put("服务端:接收到了".getBytes());
        buf.flip();
        inchannel.write(buf);

        outChannel.close();
        inchannel.close();
        sChannel.close();

    }

客户端


    @Test
    public void blockclient() throws IOException {

        SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));

        ByteBuffer buf = ByteBuffer.allocate(1024);

        FileChannel inChannell = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);

        int len;

        while ((len = inChannell.read(buf)) != -1) {
            buf.flip();    // 改为写模式
            sChannel.write(buf);
            buf.clear();
        }

        sChannel.shutdownOutput();

        int len1;
        ByteBuffer buf1 = ByteBuffer.allocate(1024);
        while ((len1 = sChannel.read(buf1)) != -1) {
            buf1.flip();    // 改为写模式
            System.out.println(new String(buf1.array(), 0, len1));
            buf1.clear();
        }

        inChannell.close();
        sChannel.close();


    }

2 非阻塞式

服务端

 @Test
    public void server() throws IOException {
        // 1 开启通道
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // 2 创建缓冲区
        //  ByteBuffer.allocate(1024);
        // 3 绑定端口
        serverSocketChannel.bind(new InetSocketAddress(9898));
        // 4 开启非阻塞
        serverSocketChannel.configureBlocking(false);

        // 5 获取选择器
        Selector sel = Selector.open();

        // 6 通道注册到选择器上,并选择模式
        serverSocketChannel.register(sel, SelectionKey.OP_ACCEPT);

        // 7 轮询获取选择器上已经准备好的事件
        while (sel.select() > 0) {

            Iterator<SelectionKey> iterator = sel.selectedKeys().iterator();
            while (iterator.hasNext()) {
                // 获取已经准备好的事件
                SelectionKey sk = iterator.next();

                if (sk.isAcceptable()) {
                    // 获取客户端连接
                    SelectableChannel schannel = serverSocketChannel.accept();
                    // 设置非阻塞式
                    schannel.configureBlocking(false);

                    // 把通道注册到选择器上
                    schannel.register(sel, SelectionKey.OP_READ);

                } else if (sk.isReadable()) {
                    // 获取读就绪通道
                    SocketChannel cs = (SocketChannel) sk.channel();

                    //  创建缓冲区
                    ByteBuffer buf = ByteBuffer.allocate(1024);

                    int len = 0;
                    while ((len = cs.read(buf)) > 0) {
                        buf.flip();
                        System.out.println(new String(buf.array(), 0, len));
                        buf.clear();
                    }

                }
                // 取消选择键
                iterator.remove();

            }

        }
        serverSocketChannel.close();

    }

客户端


public class Client1 {
    public static void main(String[] args) throws IOException {

        SocketChannel channel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));

        ByteBuffer buf = ByteBuffer.allocate(1024);

        channel.configureBlocking(false);
        Scanner scanner = new Scanner(System.in);


        while (scanner.hasNext()) {

            String str = scanner.next();
            if("e".equals(str)){
                break;
            }
            buf.put(("客户端1 :" + str).getBytes());
            buf.flip();

            channel.write(buf);
            buf.clear();


        }

        channel.close();

    }
}

UDP

发送

    @Test
    public void send() throws IOException {
        DatagramChannel channel = DatagramChannel.open();

        ByteBuffer buf = ByteBuffer.allocate(1024);

        channel.configureBlocking(false);
        buf.put("发送端: 发送".getBytes());
        buf.flip();
        channel.send(buf, new InetSocketAddress("127.0.0.1", 9898));
        buf.clear();
        channel.close();


    }

接收

  @Test
    public void receive() throws IOException {
        DatagramChannel rc = DatagramChannel.open();
        rc.bind(new InetSocketAddress(9898));
        rc.configureBlocking(false);

        Selector selector = Selector.open();
        rc.register(selector, SelectionKey.OP_READ);


        while (selector.select() > 0) {
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();

            while (iterator.hasNext()) {
                SelectionKey sk = iterator.next();

                if (sk.isReadable()) {
                    ByteBuffer buf = ByteBuffer.allocate(1024);

                    rc.receive(buf);
                    buf.flip();
                    System.out.println(new String(buf.array(), 0, buf.limit()));
                    buf.clear();

                }


            }
            iterator.remove();


        }


    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值