1.Netty中抽象的接口
主要有三种类型接口
- Channel -> Socket
- EventLoop -> 控制流、多线程处理、并发
- ChannelFuture -> 异步通知
下面一一介绍
1.1.Channel
接口
Channel
的产生是为了降低网络传输变成的复杂性,它是传入传出数据的载体,可以打开或者关闭,连接或断开。可以当做它是Socket的升级。我们之前用的NioSocketChannel
就是它的实现类。
内部结构:
1.2.EventLoop
接口
这个接口是Netty的核心抽象,用于处理连接中所发生的事件。
- 一个
EventLoopGroup
包含一个或者多个EventLoop
- 一个
EventLoop
在它的生命周期内只和一个Thread绑定 - 所有的
EventLoop
处理IO事件都将传给它专有的Thread上处理 - 一个Cahnnel在它的生命周期内只注册一个
EventLoop
- 一个
EventLoop
可能会被分配多个或者一个Channel
1.3.ChannelFuture
接口
Netty中所有的IO操作都是异步的,一个操作不会立即返回,我们会在特定的事件点需要其返回结果。ChannelFuture
接口就可以看做将来结果的占位符。
2.逻辑处理(Handler)和处理数据流(Pipe)接口
2.1.ChannelHandler
接口
它充当了所有处理入站和出站数据的应用程序逻辑的容器。它的方法是由事件触发的。它可以用于几乎任何类型的动作,如数据格式转换或者异常抛出。
ChannelHandler
有很多种类型,它的功能取决于它的超类,Netty以适配器的形式提供了大量的默认实现。默认适配器的存在是为了简化应用程序的开发过程。ChannelPipeline
的每个ChannelHandler
将负责将事件转发到下一个ChannelHandler
。我们只需要重写那些需要特殊处理的方法和事件。
常用的适配器
- 编码器、解码器
SimpleChannelInboundHandlerAdapter
2.1.1.编码器和解码器
所有的编码器/解码器适配器类型都实现了ChannelInboundHandler
或ChannelOutboundHandler
接口。
当Netty接收或者发送一个消息时,就会有数据转换。入站数据会被解码,即从字节转换为另一种格式。如果出站则被编码为字节。
如果需要中间的一种格式,类似于Google的Protocol Buffers需要一种特别的格式,则可以自定义一种编码器、解码器。
2.1.2.抽象类SimpleChannelInboundHandlerAdapter
public class ClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
@Override
//当被通知Channel是活跃的时候,发送一条消息
public void channelActive(ChannelHandlerContext ctx) {
ctx.writeAndFlush(Unpooled.copiedBuffer("Netty is No.1", CharsetUtil.UTF_8));
}
@Override
//接收消息时会调用该方法
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
System.out.println("Client Recived:" + msg.toString(CharsetUtil.UTF_8));
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
上面的代码中我们继承了SimpleChannelInboundHandlerAdapter
抽象类,我们重写了channelRead0
方法,并且得到了ChannelHandlerContext
的引用,这个引用将作为参数传递给ChannelHandler
的所有方法。
2.2.ChannelPipeline
接口
ChannelPipeline
提供了ChannelHandler
链的容器,并定义了用于该链上传播入站和出站事件流的API。当Channel被创建时,它会被自动分配到他专属的ChannelPipeline
然我们看看ChannelHandler
安装到ChannelPipeline
中的过程
bootstrap.group(group)
//适用于Nio传输的Channel类型
.channel(NioSocketChannel.class)
.remoteAddress(new InetSocketAddress(host, port))
//ChannelInitializer的实例被注册到ServerBootstrap
//在创建Channel时,向ChannelPipeline添加一个ClientHandler实例
.handler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ClientHandler());
}
});
ChannelHandler
有俩个子接口ChannelInboundHandler
和ChannelOutboundHandler
分别处理入站和出站事件
举个例子:
可以看出ChannelHandler
接收事件、执行处理逻辑。并将数据传递给下一个ChannelHandler
,他们的执行顺序是由他们被添加的顺序决定的。当然是ChannelPipeline
给他们提供了平台。当然ChannelPipeline
可以区分出是入站和出站,可以保证数据在相同类型的ChannelHandler
之间传递。
3.引导
引导类主要作用是将一个进程连接到一个端口上,或者将一个进程连接到指定的主机上。一次有两种引导,一种是客户端Bootstrap
和服务器ServerBootstrap
重要的一点
Bootstrap
只需要一个EventLoopGroup
,但是ServerBootstrap
需要两个。因为一组在端口接听套接字,另一组用来处理传入的客户端连接。当然这两组可以是同一个引用。
下一篇:http://blog.csdn.net/theludlows/article/details/79501294