Netty网络编程(二)

ByteBuf、ChannelHandler和ChannelPipeline、EventLoop和线程模型详述

ByteBuf

工作方式:ByteBuf维护了两个不同的的索引,一个用于读取,一个用于写入。从ByteBuf读取数据时readerIndex将会递增已被读取字节数,写入ByteBuf时,writeIndex也会递增。
:名称以read\write开头方法会推进索引,而set\get开头的方法不会。

ByteBuf的使用模式

  1. 堆缓冲区,将数据存储在JVM的堆空间中。这种模式被称为支撑数组(backing array),能在没有使用池化的情况下提供快速的分配和释放内存
  2. 直接缓冲区:允许JVM通过本地调用来分配内存。直接缓冲区的内容不在会被常规垃圾回收的堆区,缺点在于其内存分配和释放都较为昂贵。
  3. 复合缓冲区:可以为多个ByteBuf提供一个聚合视图,通过CompositeByteBuf子类将多个缓冲区表示为单个合并缓冲区的虚拟表示

ChannelHandler

  Channel的生命周期状态

状态描述
ChannelRegisteredChannel已经被注册到EventLoop
ChannelUnregisteredChannel已经被创建,但还未注册到EventLoop
ChannelActiveChannel处于活动状态(已经链接到远程节点),可以接受和发送数据
ChannelInactiveChannel没有链接到远程节点

当Channel的生命周期状态改变时,会生成对应的事件,转发给ChannelPipeline的ChannelHandler,对其做出响应
  ChannelHandler的生命周期方法(每个方法都会接受一个ChannelHandlerContext参数)

类型操作
handlerAdded当把ChannelHandler添加到ChannelPipeline中时调用
handlerRemoved从ChannelPipeline中移除ChannelHandler时调用
execptionCaught处理过程中ChannelPipeline出现错误时调用

ChannelHandler的子接口:

  • ChannelInboundHandler——处理入站数据以及各种状态变化
    • channelRegister
    • channelUnregistered
    • channelActive
    • channelInactive
    • channelRead
    • ChannelWritabilityChanged(Channel可写状态改变时调用)
    • userEventTriggered
  • ChannelOutboundHandler——处理出站数据并且允许拦截所有操作
    • bind(绑定到本地地址)
    • connect(链接到远程地址)
    • disconnect
    • close
    • deregister
    • read
    • flush
    • write

ChannelPipeline接口

  ------一个拦截流经Channel的入站和出站事件的ChannelHandler实例链。
每个新创建的Channel都会分配给一个新的Channelpipeline,Channel不能附加到另外一个ChannelPipeline,也不能分离当前的。

  • ChannelPipeline保存了与Channel相关联的ChannelHandler
  • ChannelPipeline可以根据需要,通过添加或删除ChannelHandler来动态的修改
  • ChannelPipeline有着丰富的API用以调用,以响应出站和入站事件
  • ChannelHandlerContext
     ChannelHandlerContext使得ChannelHandler能够和它的ChannelPipeline以及其他的Channelhandler交互
    在ChannelPipeline中传播事件时,它会测试ChannelPipeline中的下一个ChannelHandler的类型是否与事件的运动方向相匹配,如不匹配则跳过该ChannelHandler前进到下一个,直到找到匹配的为止。

ChannelHandler用于修改ChannelPipeline的方法

名称描述
addFirst
addBefore
addAfter
addLast
将一个ChannelHandler添加到ChannelPipeline中
remove将一个ChannelHandler从ChannelPipeline中移除
replace将ChannelPipeline中的一个ChannelHandler替换为另一个ChannelHandler

ChannelHandlerContext接口

ChannelHandlerContext代表了ChannelHandler和Channel Pipeline之间的关联,当有ChannelHandler添加到ChannelPipeline中时就会创建ChannelHandlerContext
一个ChannelHandler可以从属于多个ChannelPipeline,所以可以绑定多个ChannelHanlderContext实例。多个ChannelPipeline共享一个ChannelHandler时,对应的ChannelHandler必须使用@Sharable注解标注,而且应该确定了ChannelHandler时线程安全的情况下才能使用。

异常处理

处理入站异常
  • 发生异常时会继续按照入站方向流动,确保异常总是会被处理。exceptionCaught的默认实现是简单的将异常转发给下一个ChannelHandler
  • 如果异常到达ChannelPipeline的尾端,它会被记录成未被处理
  • 若要自定义处理逻辑,需重写exceptionCaught方法
处理出站异常
  • 每个出站操作将会返回一个ChannelFuture,注册到ChannelFuture的ChannelFutureListener将会在操作完成时通知该操作是成功了还是出错了
  • 几乎所有ChannelOutboundHandler都有ChannelPromise实例,可以分配用于异步通知的监听器,也可以提供立即通知的可写方法setSuccess和setFaulure

EventLoop和线程模型

线程模型指定了操作系统、编程语言、框架或者应用程序的上下文的线程管理的关键方面。
事件循环:运行任务来处理在链接的生命周期内发生的事件
一个EventLoop将由一个永远不会改变的Thread驱动,同时任务可以直接提交给EventLoop实现,以立即执行或调度执行。
在Netty4中,所有I/O操作和事件都由已经被分配给EventLoop的那个Thread处理。
如果当前调用线程正式支撑EventLoop的线程,那么所提交的代码就会被直接执行,否则EventLoop将会调度该任务以便稍后执行,并将他放入队列中,当EventLoop下次处理它的事件时,就会执行队列中的事件。
使用EventLoop调度任务

//调度任务在从现在的60秒后执行
Channel ch = ...
ScheduledFuture<?> future = ch.eventLoop().schedule(
	new Runnable(){
	@Override
	public void main(){
		System.out.println("60 seconds later...");
	}
},60,TimeUnit.SECONDS);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值