Java NIO: Comprensión de la dispersión y la recopilación

Análisis de ejemplo

package com.leolee.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;

/**
 * @ClassName ScatteringAndGatheringTest
 * @Description: TODO
 * @Author LeoLee
 * @Date 2020/9/20
 * @Version V1.0
 **/
public class ScatteringAndGatheringTest {

    public static void test () throws IOException {

        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        InetSocketAddress inetSocketAddress = new InetSocketAddress(8899);
        serverSocketChannel.socket().bind(inetSocketAddress);

        SocketChannel socketChannel = serverSocketChannel.accept();

        int messageLength = 2 + 3 + 4;

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

        while (true) {
            int bytesRead = 0;

            while (bytesRead < messageLength) {
                long r = socketChannel.read(byteBuffers);
                bytesRead += r;

                System.out.println("bytesRead:" + bytesRead);
                System.out.println("after read,show every buffer:");

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

            Arrays.asList(byteBuffers).forEach(byteBuffer -> {
                byteBuffer.flip();
            });

            long bytesWrite = 0;
            while (bytesWrite < messageLength) {
                long w = socketChannel.write(byteBuffers);
                bytesWrite += w;
            }

            Arrays.asList(byteBuffers).forEach(byteBuffer -> {
                byteBuffer.clear();
            });

            System.out.println("bytesRead:" + bytesRead + ",bytesWrite:" + bytesWrite + ",messageLength:" + messageLength);

        }
    }

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

        ScatteringAndGatheringTest.test();
    }
}

Interpretación del código:

  • Al abrir un canal de socket de servidor NIO como receptor que recibe datos de socket enviados por el cliente, ingresa en un bucle sin fin después de ejecutar para simular el servidor sin salir
  • MessageLength definido como el límite de recepción de mensajes y una matriz de búfer, esta matriz de búfer contiene tres búferes, el tamaño es 2, 3, 4
  • Después de que se inicie el receptor de datos del socket, leerá los datos recibidos y los volverá a escribir en el cliente intactos

resultado de la operación:

Inicie el programa y simule la solicitud a través del comando telnet

telnet localhost 8899, después de una conexión exitosa, ingrese abcd12345

El servidor imprime de la siguiente manera:

bytesRead:1
after read,show every buffer:
position:1,limit:2,capacity:2
position:0,limit:3,capacity:3
position:0,limit:4,capacity:4
bytesRead:2
after read,show every buffer:
position:2,limit:2,capacity:2
position:0,limit:3,capacity:3
position:0,limit:4,capacity:4
bytesRead:3
after read,show every buffer:
position:2,limit:2,capacity:2
position:1,limit:3,capacity:3
position:0,limit:4,capacity:4
bytesRead:4
after read,show every buffer:
position:2,limit:2,capacity:2
position:2,limit:3,capacity:3
position:0,limit:4,capacity:4
bytesRead:5
after read,show every buffer:
position:2,limit:2,capacity:2
position:3,limit:3,capacity:3
position:0,limit:4,capacity:4
bytesRead:6
after read,show every buffer:
position:2,limit:2,capacity:2
position:3,limit:3,capacity:3
position:1,limit:4,capacity:4
bytesRead:7
after read,show every buffer:
position:2,limit:2,capacity:2
position:3,limit:3,capacity:3
position:2,limit:4,capacity:4
bytesRead:8
after read,show every buffer:
position:2,limit:2,capacity:2
position:3,limit:3,capacity:3
position:3,limit:4,capacity:4
bytesRead:9
after read,show every buffer:
position:2,limit:2,capacity:2
position:3,limit:3,capacity:3
position:4,limit:4,capacity:4
bytesRead:9,bytesWrite:9,messageLength:9

Puede ver que los 9 mensajes de longitud enviados por telnet se almacenan secuencialmente en tres matrices. Cuando un búfer está lleno, se almacenará en el siguiente búfer. Esto es Dispersión , y luego el servidor devuelve todos los datos. Para el cliente, de la siguiente manera:

Esto es reunión.

comprensión

Para un diseño tan interesante en NIO, es realmente necesario. Por ejemplo, cuando se utiliza un protocolo personalizado, una secuencia de búfer ordenada (matriz de búfer) de diferentes tamaños puede decirle fácilmente al desarrollador qué información representa cada búfer y no requiere un análisis especial.

 

 

Supongo que te gusta

Origin blog.csdn.net/qq_25805331/article/details/108691831
Recomendado
Clasificación