(Netty)Manejador y Tubería

Manejador y Tubería

ChannelHandler se usa para manejar varios eventos en el canal, divididos en entrantes y salientes. Todos los ChannelHandlers están conectados en una cadena, que es el Pipeline

  • El controlador de entrada suele ser una subclase de ChannelInboundHandlerAdapter, que se utiliza principalmente para leer los datos del cliente y escribir el resultado.
  • El controlador de salida suele ser una subclase de ChannelOutboundHandlerAdapter, que procesa principalmente los resultados de reescritura.

Para usar una metáfora, cada canal es un taller de procesamiento de productos, Pipeline es la línea de ensamblaje en el taller, ChannelHandler es cada proceso en la línea de ensamblaje y el ByteBuf que se analizará más adelante es una materia prima, que se procesa a través de muchos procesos: proceso de la estación, y luego a través de una serie de procesos de salida y finalmente convertirse en un producto

Primero averigüe el orden, el servidor

new ServerBootstrap()
    .group(new NioEventLoopGroup())
    .channel(NioServerSocketChannel.class)
    .childHandler(new ChannelInitializer<NioSocketChannel>() {
    
    
        protected void initChannel(NioSocketChannel ch) {
    
    
            ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){
    
    
                @Override
                public void channelRead(ChannelHandlerContext ctx, Object msg) {
    
    
                    System.out.println(1);
                    ctx.fireChannelRead(msg); // 1 将数据传递给下一个 handler(在这里的下一个就是h2),如果不调用,调用链会断开
                    // super.channelRead(ctx, msg); // 和上面的语句是一样的作用,上面的是这个内部实现
                }
            });
            ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){
    
    
                @Override
                public void channelRead(ChannelHandlerContext ctx, Object msg) {
    
    
                    System.out.println(2);
                    ctx.fireChannelRead(msg); // 2
                }
            });
            ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){
    
    
                @Override
                public void channelRead(ChannelHandlerContext ctx, Object msg) {
    
    
                    System.out.println(3);
                    ctx.channel().write(msg); // 3
                }
            });
            
            // 只有向channel写入数据才会触发,没写入就不能触发
            ch.pipeline().addLast(new ChannelOutboundHandlerAdapter(){
    
    
                @Override
                public void write(ChannelHandlerContext ctx, Object msg, 
                                  ChannelPromise promise) {
    
    
                    System.out.println(4);
                    ctx.write(msg, promise); // 4
                }
            });
            ch.pipeline().addLast(new ChannelOutboundHandlerAdapter(){
    
    
                @Override
                public void write(ChannelHandlerContext ctx, Object msg, 
                                  ChannelPromise promise) {
    
    
                    System.out.println(5);
                    ctx.write(msg, promise); // 5
                }
            });
            ch.pipeline().addLast(new ChannelOutboundHandlerAdapter(){
    
    
                @Override
                public void write(ChannelHandlerContext ctx, Object msg, 
                                  ChannelPromise promise) {
    
    
                    System.out.println(6);
                    ctx.write(msg, promise); // 6
                }
            });
        }
    })
    .bind(8080);

cliente

new Bootstrap()
    .group(new NioEventLoopGroup())
    .channel(NioSocketChannel.class)
    .handler(new ChannelInitializer<Channel>() {
    
    
        @Override
        protected void initChannel(Channel ch) {
    
    
            ch.pipeline().addLast(new StringEncoder());
        }
    })
    .connect("127.0.0.1", 8080)
    .addListener((ChannelFutureListener) future -> {
    
    
        future.channel().writeAndFlush("hello,world");
    });

Impresión del lado del servidor:

1
2
3
6
5
4

Se puede ver que ChannelInboundHandlerAdapter se ejecuta en el orden de addLast y ChannelOutboundHandlerAdapter se ejecuta en orden inverso a addLast. La implementación de ChannelPipeline es una lista doblemente enlazada compuesta por ChannelHandlerContext (empaquetado ChannelHandler)

inserte la descripción de la imagen aquí

  • En el controlador de entrada, ctx.fireChannelRead(msg) es para llamar al siguiente controlador de entrada
    • Si se comenta 1 código, solo se imprimirá 1
    • Si se comentan 2 códigos, solo se imprimirá 1 2
  • ctx.channel().write(msg) en 3 activará la ejecución de los procesadores de salida posteriores desde el final
    • Si se comentan 3 códigos, solo se imprimirá 1 2 3
  • De manera similar, en el controlador de salida, la llamada de ctx.write(msg, promise) también activará el último controlador de salida.
    • Si se comentan 6 códigos, solo se imprimirá 1 2 3 6
  • ctx.canal().escribir(mensaje) VS ctx.escribir(mensaje)
    • Ambos desencadenan la ejecución del controlador de salida.
    • ctx.channel().write(msg) busca controladores de salida a partir de la cola
    • ctx.write(msg) es encontrar un procesador de salida desde el nodo actual
    • Si ctx.channel().write(msg) en 3 se cambia a ctx.write(msg), solo imprimirá 1 2 3, porque no hay otros procesadores de salida antes del nodo 3
    • Si ctx.write(msg, promise) en 6 se cambia a ctx.channel().write(msg), imprimirá 1 2 3 6 6 6... porque ctx.channel().write() busca desde el final, el resultado Nodo 6 en sí mismo de nuevo

Figura 1: el proceso original desencadenado por la tubería del servidor, los números en la figura representan la secuencia de pasos de procesamiento
inserte la descripción de la imagen aquí

Demostrar EmbeddedChannel , conveniente para la depuración y simulación
inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/QRLYLETITBE/article/details/128727419
Recomendado
Clasificación