Netty权威指南 第2版学习笔记9——Channel,Unsafe和 AttributeMap

来源:互联网 发布:诺基亚6730c软件 编辑:程序博客网 时间:2024/05/22 00:22

Channel功能说明

io.netty.channel.Channel是Netty网络操抽象类,它聚合了一组功能,包括但不限于网络的读、写,客户端发起连接,主动关闭连接,链路关闭,获取通信双方的网络地址等。它也包含了Netty框架相关的一些功能框架,包括获取该Channel的EventLoop,获取缓冲分配器ByteBufAllocator和pipeline等。

Channel的工作原理

Channel网络I/O相关的方法定义:
这里写图片描述

  1. Channel read():从当前的Channel中读取数据到第一个inbound缓冲区中,如果数据被成功读取,触发ChannelHandler.channelRead(ChannelHandlerContext,Object)事件,读取操作API调用完成之后,紧接着会触发ChannelHanler.channelReadComplete(ChannelHandlerContext)事件,这样业务的ChannelHandler可以决定是否需要继续读取数据。如果已经有读操作表求被挂起,则后续的读操作会被忽略。
  2. ChannelFutrue write(Object msg):当前的msg通过ChannelPipeline写入到目标Channel中。这时并没有立刻发送,要flush操作才会被写入到Channel中,发送给对方。
  3. ChannelFuture write(Object msg,ChannelPromise promise):功能同write(Object msg),但携带了ChannelPromise参数负责设置写入操作的结果。
  4. ChannelFuture writeAndFlush(Object msg,ChannelPromise promise):相当于write+flush
  5. ChannelFuture writeAndFlush(Object msg)
  6. Channel flush:写入到发送环形数组中的消息全部与入到目标Channel中。
  7. ChannelFuture close(ChannelPromise promise):主动关闭发前连接,通过Channel Promise 设置操作进行结果通知,无论操作是否成功,都可以通过ChanelPromise获取操作结果。该操作会级联触发ChannelPipeline中所有ChannelHnadler的ChannelHandler.close(ChannelHandlerContext,ChannelPromise)事件。
  8. ChannelFuture disconnect(ChannelPromise promise):请求断开与远程通信对端的连接并使用ChannelPromise 来获取操作结果的通知消息。该方法会级联触发ChannelHandler.disconnect(ChannelHandlerContext,ChannelPromise)事件。
  9. ChannelFuture connect(SocketAddress remoteAddress):客户端使用指定的服务端地址remoteAddress发起连接请求,如果连接因为应答超时而失败,ChannelFuture中的操作结果就是ConnectTimeoutException异常。 如果连接被拒绝,操作结果为ConnectException。该方法级联触发ChannelHandler.connect(ChannelHandlerContext,SocketAddress,SocketAddress,ChannelPromise)事件。
  10. ChannelFuture connect(SocketAddress remoteAddress,SocketAddress localAddress):与方法(9)功能类似,需要先绑定指定的本地地址
  11. ChannelFuture connect(SocketAddress remoteAddress,ChannelPromise promise)
  12. connect(SocketAddress remoteAddress,SocketAddress localAddress,ChannelPromise promise)
  13. ChannelFuture bind(SocketAddress localAddress)
  14. ChannelFuture bind(SocketAddress localAddress,ChannelPromise promise)
  15. ChannelConfig config():获取当前Channel的配置信息
  16. boolean isOpen():判断当前Channel是否已经打开
  17. boolean isRegistered():判断当前Channel是否已经注册到EventLoop上
  18. boolean isActive():判断当前Channel是否已经处于激活状态
  19. ChannelMetadata metadata():获取当前Channel的元数据描述信息,包括TCP参数配置等
  20. SocketAddress localAddress():获取当前Channel的本地绑定地址
  21. SocketAddress remoteAddress():获取当前Channel的远程Socket地址

Unsafe接口是Channel的一个内部接口,不应该被用户调用。

其它重要的API功能说明

eventLoop()

Channel需要注册到EventLoop的多路复用器上,用于处理I/O事件,通过eventLoop方法中以获取到Channel注册的EventLoop。EventLoop本质上就是处理网络读写事件的Reactor线程。在Netty中,它不仅仅用来处理网络事件,也可以用来执行定时任务和用户自定义NioTask等任务 。

metadata()

通过metadata()方法和来获取当前Channel的TCP参数配置

parent()

对于服务端的Channel而言,它的父Channel为空。对于客户端Channel,它的父Channel是创建它的ServerSocketChannel

id()

用来获取Channel标识,生成策略可能是:
- 机器的MAC地址
- 当前的进程ID
- 当前系统时间的毫秒
- 当前系统时间纳秒数
- 32位的随机整形数
- 32位自增的序列数

其它说明

服务端NioServerSocketChannel继承关系

这里写图片描述

客户端NioSocketChannel的继承关系类图

这里写图片描述

AttributeMap

AttributeMap是绑定在Channel或者ChannelHandlerContext上的一个附件。
ChannelHandlerContext都是ChannelHandler和ChannelPipeline之间连接的桥梁,
每一个ChannelHandlerContext都有属于自己的上下文,
每一个ChannelHandlerContext上如果有AttributeMap都是绑定上下文的,
A的ChannelHandlerContext中的AttributeMap,B的ChannelHandlerContext是无法读取到的。
但是Channel上的AttributeMap是共享的,每一个ChannelHandler都能获取到。

使用

定义

public static final AttributeKey<NettyChannel> NETTY_CHANNEL_KEY = AttributeKey.valueOf("netty.channel");  

示例这里的AttributeMap中存储NettyChannel

package com.lyncc.netty.attributeMap;  import java.util.Date;  public class NettyChannel {      private String name;            private Date createDate;        public NettyChannel(String name,Date createDate) {          this.name = name;          this.createDate = createDate;      }      public String getName() {          return name;      }      public void setName(String name) {          this.name = name;      }      public Date getCreateDate() {          return createDate;      }      public void setCreateDate(Date createDate) {          this.createDate = createDate;      }  }  

使用

@Override      public void channelActive(ChannelHandlerContext ctx) {          Attribute<NettyChannel> attr = ctx.attr(NETTY_CHANNEL_KEY);          NettyChannel nChannel = attr.get();          if (nChannel == null) {              NettyChannel newNChannel = new NettyChannel("HelloWorld0Client", new Date());              nChannel = attr.setIfAbsent(newNChannel);          } else {              System.out.println("attributeMap 中是有值的");              System.out.println(nChannel.getName() + "=======" + nChannel.getCreateDate());          }          System.out.println("HelloWorldC0ientHandler Active");          ctx.fireChannelActive();      }  

Channel的状态变换

被Bootstrap引导的NioSocketChannel在构造好之后就进入了open状态,之后通过把自己注册进EventLoop进入registered状态,接着连接服务器进入active状态。
这里写图片描述

查询状态的方法:
1. isOpen()
2. isRegistered()
3. isActive()
4. isWriteable()

本文参考:
http://blog.csdn.net/linuu/article/details/51502136
http://blog.csdn.net/zxhoo/article/details/17964353

0 0
原创粉丝点击