NIO学习(七):Java NIO的Buffer的scattering和gathering理解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/outsanding/article/details/102660802
背景
  1. scatting和gathering研究的是一个buffer数组。在这个buffer数组中持有多个Buffer实例,每个Buffer都是独立的,都有自己独立的capacity,limit,position值。
  2. buffer数组中的buffer实例唯一相互联系的地方就是:从第一个buffer数组中的Buffer实例开始,依次读满后才往后面的Buffer实例移动。写也是如此。从数组中的第一个Buffer实例中的数据依次往外写。

过程
  1. 测试代码
public static void main(String[] args) throws Exception{
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        InetSocketAddress address = new InetSocketAddress(8899);

        serverSocketChannel.socket().bind(address);

        int messageLength = 2 + 3 + 4;

        ByteBuffer[] buffers = new ByteBuffer[3];

        buffers[0] = ByteBuffer.allocate(2);
        buffers[1] = ByteBuffer.allocate(3);
        buffers[2] = ByteBuffer.allocate(4);

        SocketChannel socketChannel = serverSocketChannel.accept();

        while (true) {
            int bytesRead = 0;
            while (bytesRead < messageLength) {
                long r = socketChannel.read(buffers);
                bytesRead += r;
                System.out.println("bytesRead: " + bytesRead);

                Arrays.asList(buffers).stream().
                        map(buffer -> "position:" + buffer.position() + ", limit:" + buffer.limit()).
                        forEach(System.out::println);

                Arrays.asList(buffers).forEach(buffer -> {
                    buffer.flip();
                });

                int bytesWrite = 0;
                while (bytesWrite < messageLength) {
                    long bw = socketChannel.write(buffers);
                    bytesWrite += bw;
                }
                Arrays.asList(buffers).forEach(buffer -> {
                    buffer.clear();
                });
                System.out.println("bytesRead:" + bytesRead + ", " + "bytesWrite:" + bytesWrite + "," + "messageLength:" + messageLength);
            }
        }
    }
  1. 关键代码
		ByteBuffer[] buffers = new ByteBuffer[3];
        buffers[0] = ByteBuffer.allocate(2);
        buffers[1] = ByteBuffer.allocate(3);
        buffers[2] = ByteBuffer.allocate(4);

有一个buffer类型的数组,数组中有3个Buffer实例,每个的容量是2,3,4.

  1. 测试一(发送7个字符到服务端,最后一个回车符也算一个字符)

    客户端:
    在这里插入图片描述
    服务端:
    在这里插入图片描述
    最后一个Buffer实例,它的容量是4,但是只使用了2个。

  2. 测试二(发送9个字符到服务端)
    客户端:
    在这里插入图片描述
    服务端:
    在这里插入图片描述

  3. 测试三(发送10个字符到服务端)
    客户端:
    在这里插入图片描述
    服务端:
    在这里插入图片描述


使用场景
  1. 它的特性是天然地使用一个数组(Buffer类型的数组),而数组中就是Buffer实例,每个Buffer实例可以装独立的数据,相互之间没有任何关系。比如HTTP中请求头,请求体数据采用buffer数组来装。这个buffer数组持有两个独立的Buffer实例,一个装请求头数据,另一个装请求体数据。

小结
  1. scattering和gathering描述的Buffer类型的数组,数组中的实例是一个个Buffer实例,每个实例有独立的属性(mark,limit,position,capacity)。
  2. 通过3个测试,理解多个Buffer实例放在一个数组中的工作过程是怎样的。

猜你喜欢

转载自blog.csdn.net/outsanding/article/details/102660802