java netty之AbstractNioChannel
来源:互联网 发布:米思米 矩阵 编辑:程序博客网 时间:2024/06/05 23:19
前面的文章分析了eventloopgroup以及eventloop的继承体系,在这篇文章主要分析以下netty对channel的封装,我只对nio感兴趣,那么就只分析对nio这一部分的封装。。。。
主要来分析以下的继承体系:
channel是netty定义的顶层接口,其无非就是定义了一些基本的方法,例如返回当前channel所属的eventloop,判断channel是否已经打开,是否已经注册,本地地址,连接的远程地址等。
另外它还定义了一个十分重要的内部接口Unsfe,在这个里面的定义了一些具体的数据传输的方法,官方给出的注释给出的说明是:这里面定义的方法不应该被用户空间的代码所直接调用。。。
另外,channel还继承了AttributeMap,ChannelOutboundInvoker,ChannelPropertyAccess,Comparable接口。。。
接下来就是AbstractChannel,一个夹在中间的抽象类,它实现了一些基本的方法,另外还定义了一些属性,首先我们来看它定义的一些属性:
static final ConcurrentMap<Integer, Channel> allChannels = PlatformDependent.newConcurrentHashMap(); //静态属性,用于保存所有的channel,每个channel都对应一个负数的IDallChannels是一个静态属性,是一个ConcurrentHashMap,主要是用于保存和管理当前存在的所有channel,它的索引是一个负数的ID
private final Channel parent; //父channel private final Integer id; //当前channel的id private final Unsafe unsafe; //usafe对象 private final DefaultChannelPipeline pipeline; //当前channel的pipeline private final ChannelFuture succeededFuture = new SucceededChannelFuture(this, null); private final VoidChannelPromise voidPromise = new VoidChannelPromise(this); private final CloseFuture closeFuture = new CloseFuture(this); //close时候用到的future protected final ChannelFlushPromiseNotifier flushFutureNotifier = new ChannelFlushPromiseNotifier(); private volatile SocketAddress localAddress; //本地地址 private volatile SocketAddress remoteAddress; //连接的远程地址 private volatile EventLoop eventLoop; //所属的eventloop private volatile boolean registered; //是否已经register
上述都是一些基本的属性定义,比较重要的有定义了一个Unsafe,以及pipeline,,我们可以来看一些AbstractChannel定义的构造方法:
//abstractchannel的构造函数 protected AbstractChannel(Channel parent, Integer id) { if (id == null) { id = allocateId(this); //为当前的channel分配一个负数的id } else { if (id.intValue() < 0) { throw new IllegalArgumentException("id: " + id + " (expected: >= 0)"); } if (allChannels.putIfAbsent(id, this) != null) { throw new IllegalArgumentException("duplicate ID: " + id); } } this.parent = parent; this.id = id; unsafe = newUnsafe(); pipeline = new DefaultChannelPipeline(this); //构造pipeline //为closefuture添加一个listeer,也就是close的时候将当前channel从allChannels中移除 closeFuture().addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) { allChannels.remove(id()); } }); }还是比较简单的,首先为当前的channel分配一个id,然后构造unsfae对象,以及pipeline对象,这里newUnsafe方法是一个抽象方法,也就意味着真正unsafe的定义还要延后到子类当中去,最后还未closeFuture添加了一个listener,当channel被关闭的时候将会被调用,操作也非常简单,无非就是从allChannels静态属性中将当前channel移除。。这样垃圾回收也就能回收了。。。
另外还要分析以下在AbstractChannel中定义的AbstractUnsafe,在它里面实现了一些基本的顶层方法,我个人觉得最为重要的是register方法,该方法的作用就是将当前channel注册到eventLoop当中,不过其实最终又会调用doRegister方法,这个方法将会在AbstractNioChannel中被重写。。。
最后来分析一下AbstractNioChannel,其实它也是一个抽象类,不过它定义的一些属性和方法就很有Nio的意思了。。首先还是来分析一下它的一些属性。。。
private final SelectableChannel ch; //真正用到的channel protected final int readInterestOp; //真正关心的读事件 private volatile SelectionKey selectionKey; //注册后获取的的key稍微熟悉一点Nio的人应该就能知道这几个东西是干嘛的吧。。。首先定义了一个SelectableChannel,它是一个java Nio定义的channel,另外readInterestOp用于区分当前channel所关注的的事件类型,至于selectionKey这东西就更为直白了,它是将 SelectableChannel注册到selector后得到的。。。。
从上面一些属性的定义就可以看出,在AbstractNioChannel中就已经将Netty的channel和java nio的channel联系起来了。。
还是来看一下它的构造函数吧:
//构造函数 protected AbstractNioChannel( Channel parent, Integer id, SelectableChannel ch, int readInterestOp) { super(parent, id); this.ch = ch; this.readInterestOp = readInterestOp; try { ch.configureBlocking(false); //将channel设置为非阻塞 } catch (IOException e) { try { ch.close(); } catch (IOException e2) { if (logger.isWarnEnabled()) { logger.warn( "Failed to close a partially initialized socket.", e2); } } throw new ChannelException("Failed to enter non-blocking mode.", e); } }这里面比较有意思也是比价直白的就是将当前的selectableChannel设置为非阻塞的,看到这里就有点觉得,其实所有的编程语言和平台他们最终的实现都差不多,不管是c语言还是java,他们最终编程套路都差不多,起码在netty中我觉得和c语言的io框架的实现其实也都是差不太多的,唯一可能比较不一样的地方就是java的类封装比较漂亮,不过也稍微显的比较繁琐,没有c语言来的直白。。。
另外最后还要分析一下在AbstractNioChannel中定义的AbstractNioUnsafe,不过这里我只是想分析一下其中定义的一个方法,也就是在上面提到过的doRegister方法:
@Override //channel的regist protected Runnable doRegister() throws Exception { boolean selected = false; for (;;) { try { //获取实际的channel然后注册到eventloop的selector上面 selectionKey = javaChannel().register(eventLoop().selector, 0, this); return null; } catch (CancelledKeyException e) { if (!selected) { // Force the Selector to select now as the "canceled" SelectionKey may still be // cached and not removed because no Select.select(..) operation was called yet. eventLoop().selectNow(); selected = true; } else { // We forced a select operation on the selector before but the SelectionKey is still cached // for whatever reason. JDK bug ? throw e; } } } }上面的代码就将netty的channel和java nio完全的联系起来了。。。这里eventLoop方法返回的是一个NioEventLoop对象,在它里面定义了selector属性,doRegister的主要作用就是将当前对象的selectableChannel注册到eventLoop的selector去,并保存返回的key。
好了,这篇文章好像写的比较多了,不过它确实比较重要,清清楚楚的将netty与java nio联系了起来。。。。
- java netty之AbstractNioChannel
- Java netty之NioServerSocketChannel
- java netty之NioSocketChannel
- java netty之ChannelPipeline
- java netty之DefaultChannelHandlerContext
- java netty之DefaultChannelPipeline
- java netty之ChannelInitializer
- java netty之ChannelInboundByteHandlerAdapter
- java netty之ByteToMessageDecoder
- java netty之MessageToByteEncoder
- java netty之ByteToMessageDecoder
- java netty之ChannelInitializer
- Netty之java序列化
- Netty 之 netty源码学习之大话java NIO
- java netty之ServerBootstrap的启动
- java netty handler之ChannelInboundHander与ChannelOutboundHandler
- Netty 权威指南之java 序列化
- Netty之Java堆外内存
- Apache Mina 白名单实现方法
- Git 常用命令
- js获取url参数值
- Boost库中date_time库介绍
- 一个完整的编译器前端实验
- java netty之AbstractNioChannel
- 砝码称重
- 安装Oracle 11g 客户端(client)先决条件检查显示NA失败错误
- ubuntu的回收站路径
- JPEG文件编/解码详解
- 数据库操作示例(B/S结构)
- Git 基本命令(摘自gihub)
- 黑马程序员_集合
- struts2的具体执行流程