【netty】ChannelPipeline、ChannelHandlerContext、AbstractChannelHandlerContext、DefaultChannelPipeline

前言

我们一般定义一个Handler,在channelRead0()的入参中,有ChannelHandlerContext 对象ctx:

public class HttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {

	@Override
	protected void channelRead0(ChannelHandlerContext ctx,
			FullHttpRequest request) throws Exception {
		 if (!request.decoderResult().isSuccess()) {
	            sendError(ctx, BAD_REQUEST);
	            return;
	        }
		 System.out.println("Http Server receive the request : " + request);
		 ByteBuf body = request.content().copy();
		 FullHttpResponse response = new DefaultFullHttpResponse(
	                HTTP_1_1, HttpResponseStatus.OK, body);
		 response.headers().set(HttpHeaderNames.CONTENT_LENGTH, body.readableBytes());
		 ctx.writeAndFlush(response).sync();
		 System.out.println("Http Server send response succeed : " + response);		 
	}

ChannelHandlerContext 是什么东西呢?

ChannelHandlerContext (子类类是AbstractChannelHandlerContext)其实是一个双向链表,对应一个ChannelPipeline,它是ChannelPipeline的工具,负责管理一组Handler。
在这里插入图片描述

1. ChannelHandler

在这里插入图片描述
ChannelHandler下主要是两个子接口:

  • ChannelInboundHandler(入站): 处理输入数据和Channel状态类型改变。

          适配器: ChannelInboundHandlerAdapter(适配器设计模式)
    
          常用的: SimpleChannelInboundHandler
    
  • ChannelOutboundHandler(出站): 处理输出数据

       适配器: ChannelOutboundHandlerAdapter
    

作用是负责处理业务。

2. ChannelPipeline

在这里插入图片描述
ChannelPipeline类是ChannelHandler实例对象的链表,用于处理或截获通道的接收和发送数据。它提供了一种高级的截取过滤模式(类似serverlet中的filter功能),让用户可以在ChannelPipeline中完全控制一个事件以及如何处理ChannelHandler与ChannelPipeline的交互。

对于每个新的通道Channel(一个通道就是一个客户端发起的连接),都会创建一个新的ChannelPipeline,并将器pipeline附加到channel中。

下图描述ChannelHandler与pipeline中的关系,一个io操作可以由一个ChannelInboundHandler或ChannelOutboundHandle进行处理,并通过调用ChannelInboundHandler处理入站io或通过ChannelOutboundHandler处理出站IO。

在这里插入图片描述

3. ChannelHandlerContext

ChannelPipeline并不是直接管理ChannelHandler,而是通过ChannelHandlerContext来间接管理,这一点通过ChannelPipeline的默认实现DefaultChannelPipeline可以看出来。

当然,存在继承链,ChannelHandlerContext、AbstractChannelHandlerContext、DefaultChannelPipeline
在这里插入图片描述

DefaultChannelHandlerContext和DefaultChannelPipeline是ChannelHandlerContext和ChannelPipeline的默认实现。

3.1 AbstractChannelHandlerContext

    // 组成双向链表
    volatile AbstractChannelHandlerContext next;
    volatile AbstractChannelHandlerContext prev;

3.2 DefaultChannelHandlerContext

DefaultChannelHandlerContext组成了一个双向链表。 我们看下DefaultChannelPipeline的构造函数:

/**
  * 可以看到,DefaultChinnelPipeline 内部使用了两个特殊的Hander 来表示Handel链的头和尾。
  */
 public DefaultChannelPipeline(AbstractChannel channel) {
        if (channel == null) {
            throw new NullPointerException("channel");
        }
        this.channel = channel;
        //尾节点
        TailHandler tailHandler = new TailHandler();
        tail = new DefaultChannelHandlerContext(this, null, generateName(tailHandler), tailHandler);
        //头节点 
        HeadHandler headHandler = new HeadHandler(channel.unsafe());
        head = new DefaultChannelHandlerContext(this, null, generateName(headHandler), headHandler);
 
        head.next = tail;
        tail.prev = head;
    }

所以对于DefaultChinnelPipeline它的Handel头部和尾部的Handel是固定的,我们所添加的Handel是添加在这个头和尾之前的Handel。(下面这个图更加清晰):
在这里插入图片描述

4. 几者关系

先大致说下什么是Channel

通常来说, 所有的 NIO 的 I/O 操作都是从 Channel 开始的. 一个 channel 类似于一个 stream。在Netty中,Channel是客户端和服务端建立的一个连接通道。

虽然java Stream 和 NIO Channel都是负责I/O操作,但他们还是有许多区别的:

1)我们可以在同一个 Channel 中执行读和写操作, 然而同一个 Stream 仅仅支持读或写。

2)Channel 可以异步地读写, 而 Stream 是阻塞的同步读写。
3)Channel 总是从 Buffer 中读取数据, 或将数据写入到 Buffer 中。

几者的关系图如下:
在这里插入图片描述
总结:

  一个Channel包含一个ChannelPipeline,创建Channel时会自动创建一个ChannelPipeline,每个Channel都有一个管理它的pipeline,这关联是永久性的。

这点从源码中就可以看出,我之前写的博客里有说到:【Netty】5 源码 Bootstrap。每一个ChannelPipeline中可以包含多个ChannelHandler。所有ChannelHandler

都会顺序加入到ChannelPipeline中,ChannelHandler实例与ChannelPipeline之间的桥梁是ChannelHandlerContext实例。

参考

【Netty】(8)—理解ChannelPipeline
Netty源码_AbstractChannelHandlerContext详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值