Netty核心组件
Channel
ChannelFuture
EventLoop
ChannelHandler
ChannelPipeline
Channel、EventLoop 和 ChannelFuture
Channel、EventLoop 和 ChannelFuture这三个抽象类聚合在一起,可以被认为是 Netty 网络抽象的代表:
Channel—Socket;
EventLoop—控制流、多线程处理、并发;
ChannelFuture—异步通知。
1.Channel接口
基本的 I/O 操作(bind()、connect()、read()和 write())依赖于底层网络传输所提供的原语。在基于 Java 的网络编程中,其基本的构造是 class Socket。Netty 的 Channel 接 口所提供的 API,大大地降低了直接使用 Socket 类的复杂性。channel是一个管道,用于连接字节缓冲区Buf和另一端的实体,这个实例可以是Socket,也可以是File, 在Nio网络编程模型中, 服务端和客户端进行IO数据交互(得到彼此推送的信息)的媒介就是Channel.
ChannelId id();
//返回channel所注册的 eventLoop
EventLoop eventLoop();
//返回当前Channel的父channel
Channel parent();
//关于channel的 一些列配置信息
ChannelConfig config();
//检查channel是否开启
boolean isOpen();
//检查channel是否注册
boolean isRegistered();
//检查channel是否存活
boolean isActive();
// 返回channel的元数据
ChannelMetadata metadata();
// 服务器的ip地址
SocketAddress localAddress();
// remoteAddress 客户端的ip地址
SocketAddress remoteAddress();
ChannelFuture closeFuture();
boolean isWritable();
long bytesBeforeUnwritable();
long bytesBeforeWritable();
//内部的一个Unsafe方法
Channel.Unsafe unsafe();
// 返回Channel的管道
ChannelPipeline pipeline();
ByteBufAllocator alloc();
Channel read();
Channel flush();
public interface Unsafe {
Handle recvBufAllocHandle();
SocketAddress localAddress();
SocketAddress remoteAddress();
// 把channel注册进EventLoop
void register(EventLoop var1, ChannelPromise var2);
//给channel绑定一个 adress
void bind(SocketAddress var1, ChannelPromise var2);
//......
void connect(SocketAddress var1, SocketAddress var2, ChannelPromise var3);
void disconnect(ChannelPromise var1);
void close(ChannelPromise var1);
void closeForcibly();
void deregister(ChannelPromise var1);
void beginRead();
void write(Object var1, ChannelPromise var2);
void flush();
ChannelPromise voidPromise();
ChannelOutboundBuffer outboundBuffer();
}
此外,Channel 也是拥有许多预定义的、专门化实现的广泛类层次结构的根,下面是一个简短的部分清单:
EmbeddedChannel;
LocalServerChannel;
NioDatagramChannel;
NioSctpChannel;
NioSocketChannel。
EventLoop 接口
EventLoop 定义了 Netty 的核心抽象,用于处理连接的生命周期中所发生的事件。运行任务处理的在编程上的构造通常称作事件循环,Netty使用EventLoop来描述。一个EventLoop将由一个永远不会变的Thread驱动,它可以被指派给多个channel,任务提交给Eventloop之后可以立即执行或者调度执行。任务的执行顺序是以先进先出的顺序执行。
一个 EventLoopGroup 包含一个或者多个 EventLoop;
一个 EventLoop 在它的生命周期内只和一个 Thread 绑定;
所有由 EventLoop 处理的 I/O 事件都将在它专有的 Thread 上被处理;
一个 Channel 在它的生命周期内只注册于一个 EventLoop;
一个 EventLoop 可能会被分配给一个或多个 Channel。
关系如下图:
ChannelFuture接口
Netty 为异步非阻塞,即所有的 I/O 操作都为异步的,因此,我们不能立刻得知消息是否已经被处理了。JDK 预置了 interface java.util.concurrent.Future,但是其所提供的实现,只 允许手动检查对应的操作是否已经完成,或者一直阻塞直到它完成。这是非常繁琐的,所以 Netty 提供了它自己的实现——ChannelFuture,用于在执行异步操作的时候使用。通过该接口的 addListener() 方法注册一个ChannelFutureListener,当操作执行成功或者失败时,监听就会自动触发返回结果。
Channel channel = ...
ChannelFuture future = channel.connect(new InetSocketAddress("192.168.0.1",6666));
// 注册一个监听器
future.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (future.isSuccess()) {
// do something....
} else {
// 输出错误信息
Throwable cause = future.cause();
cause.printStackTrace();
// do something....
}
}
});
ChannelFutureListener接口中还提供了几个简单的默认实现
public interface ChannelFutureListener extends GenericFutureListener<ChannelFuture> {
// 在Future完成时关闭
ChannelFutureListener CLOSE = new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
future.channel().close();
}
};
// 如果失败则关闭
ChannelFutureListener CLOSE_ON_FAILURE = new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
if (!future.isSuccess()) {
future.channel().close();
}
}
};
// 将异常信息传递给下一个ChannelHandler
ChannelFutureListener FIRE_EXCEPTION_ON_FAILURE = new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
if (!future.isSuccess()) {
future.channel().pipeline().fireExceptionCaught(future.cause());
}
}
};
}
ChannelHandler和ChannelPipeline
ChannelHandler
ChannelHandler属于业务的核心接口,用于处理IO事件或者拦截IO操作,并将其转发到ChannelPipeline(业务处理链)中的下一个处理程序。
ChannelHandler的主要用途包括:
对入站与出站数据的业务逻辑处理
记录日志
将数据从一种格式转换为另一种格式,实现编解码器。以一次HTTP协议(或者其他应用层协议)的流程为例,数据在网络传输时的单位为字节,当客户端发送请求到服务器时,服务器需要通过解码器(处理入站消息)将字节解码为协议的消息内容,服务器在发送响应的时候(处理出站消息),还需要通过编码器将消息内容编码为字节。
捕获异常
提供Channel生命周期内的通知,如Channel活动时与非活动时
入站消息与出站消息由其对应的接口ChannelInboundHandler与ChannelOutboundHandler负责,这两个接口定义了监听Channel的生命周期的状态改变事件的回调函数。ChannelInboundHandlerAdapter与ChannelOutboundHandlerAdapter都继承于ChannelHandlerAdapter,该抽象类简单实现了ChannelHandler接口。
Pipeline与ChannelPipeline
ChannelPipeline是一个handler的集合,它负责处理和拦截出站和入站的事件和操作。ChannelPipeline实现了拦截过滤器模式,使用户能控制事件的处理方式。在Netty中,每个Channel都有且只有一个ChannelPipeline与之对应。
一个 Channel 包含了一个 ChannelPipeline,而 ChannelPipeline 中又维护了一个由 ChannelHandlerContext 组成的双向链表,并且每个 ChannelHandlerContext 中又关联着一个 ChannelHandler。
小结
上图中各个组件关系如下:
1.最重要的就是NioEventLoop,起了两种类型的线程,一个是监听客户端连接,另一个是处理客户端读写
2.channel就是对一条连接的封装,在channel封装的api中可以进行数据读写
3.对数据的读写可以看做是逻辑处理的链(Pipeline),每一个的逻辑处理都是一个ChannelHandler
4.在一条channel中的数据读写都是基于ByteBuffer来操作的。
参考:https://blog.csdn.net/a724888/article/details/80742828
https://www.cnblogs.com/clawhub/p/11968113.html