pipline与channelHandler
在服务端或者客户端收到数据之后的处理流程大致分为以下几步:
在Netty中pipline和ChannelHandler通过责任链设计模式来组织代码逻辑,并且能够支持逻辑的动态添加和删除,Netty能够支持各类协议的扩展。
pipline与channelHandler的构成
基本构成示意图:
无论在客户端还是服务端,一条连接对应着一个Channel,每一个Channel所有的处理逻辑都在一个叫做ChannelPipline的对象里边,ChannelPipline是一个双向链表,ChannelPiplin与Channel是一一对应的。
ChannelPipeline每一个节点都是ChannelHandlerContext对象,ChannelHandlerContext能够获取到Channel相关的所有上下文信息,ChannelHandlerContext又包含了一个ChannelHandler。
ChannelHandler的分类
ChannelHandler主要有以下两个子接口:
子接口 | 子接口说明 | 子接口实现类 |
---|---|---|
ChannelInboundHandler | 处理读数据的逻辑 | ChannelInboundHandlerAdapter |
ChannelOutboundHandler | 处理写数据的逻辑 | ChannelOutboundHandlerAdapter |
ChannelInboundHandler的事件传播
Server端示例代码;
/**
* @program: learnnetty
* @description: 事件传播
* @create: 2020-05-08 16:40
**/
public class Server {
public static void main(String[] args) {
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
nioSocketChannel
.pipeline()
.addLast(new InboundHandlerA())
.addLast(new InboundHandlerB())
.addLast(new InboundHandlerC());
}
});
bootstrap.bind("127.0.0.1", 8080);
}
}
处理器A示例代码:
/**
* @program: learnnetty
* @description: 处理器A
* @create: 2020-05-08 16:41
**/
public class InboundHandlerA extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("InboundHandlerA:" + msg);
super.channelRead(ctx, msg);
}
}
处理器B示例代码:
/**
* @program: learnnetty
* @description: 处理器B
* @create: 2020-05-08 16:42
**/
public class InboundHandlerB extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("InboundHandlerB:" + msg);
super.channelRead(ctx, msg);
}
}
处理器C示例代码:
/**
* @program: learnnetty
* @description: 处理器C
* @create: 2020-05-08 16:42
**/
public class InboundHandlerC extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("InboundHandlerC:" + msg);
super.channelRead(ctx, msg);
}
}
输出:
InboundHandlerA:PooledUnsafeDirectByteBuf(ridx: 0, widx: 2, cap: 1024)
InboundHandlerB:PooledUnsafeDirectByteBuf(ridx: 0, widx: 2, cap: 1024)
InboundHandlerC:PooledUnsafeDirectByteBuf(ridx: 0, widx: 2, cap: 1024)
更换Server中Handler的顺序:
/**
* @program: learnnetty
* @description: 事件传播
* @create: 2020-05-08 16:40
**/
public class Server {
public static void main(String[] args) {
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
nioSocketChannel
.pipeline()
.addLast(new InboundHandlerC())
.addLast(new InboundHandlerA())
.addLast(new InboundHandlerB());
}
});
bootstrap.bind("127.0.0.1", 8080);
}
}
更改顺序后的输出:
InboundHandlerC:PooledUnsafeDirectByteBuf(ridx: 0, widx: 2, cap: 1024)
InboundHandlerA:PooledUnsafeDirectByteBuf(ridx: 0, widx: 2, cap: 1024)
InboundHandlerB:PooledUnsafeDirectByteBuf(ridx: 0, widx: 2, cap: 1024)
可以看到读处理器的处理顺序与在引导类中添加处理器的顺序有关。
ChannelOutboundHandler的事件传播
Server端示例代码:
/**
* @program: learnnetty
* @description: 事件传播
* @create: 2020-05-08 16:40
**/
public class Server {
public static void main(String[] args) {
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
nioSocketChannel
.pipeline()
.addLast(new InboundHandlerA())
.addLast(new OutboundHandlerA())
.addLast(new OutboundHandlerB())
.addLast(new OutboundHandlerC());
}
});
bootstrap.bind("127.0.0.1", 8080);
}
}
用于做出反馈信息的HandlerA:
/**
* @program: learnnetty
* @description: 处理器A
* @create: 2020-05-08 16:41
**/
public class InboundHandlerA extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
super.channelRead(ctx, msg);
ctx.channel().writeAndFlush(Unpooled.wrappedBuffer("1".getBytes()));
}
}
写处理器HandlerA:
/**
* @program: learnnetty
* @description: 处理器A
* @create: 2020-05-08 16:54
**/
public class OutboundHandlerA extends ChannelOutboundHandlerAdapter {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
System.out.println("OutboundHandlerA:" + msg);
super.write(ctx, msg, promise);
}
}
写处理器HandlerB:
/**
* @program: learnnetty
* @description: 处理器B
* @create: 2020-05-08 16:55
**/
public class OutboundHandlerB extends ChannelOutboundHandlerAdapter {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
System.out.println("OutboundHandlerB:" + msg);
super.write(ctx, msg, promise);
}
}
写处理器HandlerC:
/**
* @program: learnnetty
* @description: 处理器C
* @create: 2020-05-08 16:55
**/
public class OutboundHandlerC extends ChannelOutboundHandlerAdapter {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
System.out.println("OutboundHandlerC:" + msg);
super.write(ctx, msg, promise);
}
}
输出:
OutboundHandlerC:UnpooledHeapByteBuf(ridx: 0, widx: 1, cap: 1/1)
OutboundHandlerB:UnpooledHeapByteBuf(ridx: 0, widx: 1, cap: 1/1)
OutboundHandlerA:UnpooledHeapByteBuf(ridx: 0, widx: 1, cap: 1/1)
根据输出可以看到写处理器的执行顺序与在引导类中添加的顺序相反。
完整的Server示例代码:
/**
* @program: learnnetty
* @description: 事件传播
* @create: 2020-05-08 16:40
**/
public class Server {
public static void main(String[] args) {
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
nioSocketChannel
.pipeline()
.addLast(new InboundHandlerA())
.addLast(new InboundHandlerB())
.addLast(new InboundHandlerC())
.addLast(new OutboundHandlerA())
.addLast(new OutboundHandlerB())
.addLast(new OutboundHandlerC());
}
});
bootstrap.bind("127.0.0.1", 8080);
}
}
输出:
InboundHandlerA:PooledUnsafeDirectByteBuf(ridx: 0, widx: 2, cap: 1024)
InboundHandlerB:PooledUnsafeDirectByteBuf(ridx: 0, widx: 2, cap: 1024)
InboundHandlerC:PooledUnsafeDirectByteBuf(ridx: 0, widx: 2, cap: 1024)
OutboundHandlerC:UnpooledHeapByteBuf(ridx: 0, widx: 1, cap: 1/1)
OutboundHandlerB:UnpooledHeapByteBuf(ridx: 0, widx: 1, cap: 1/1)
OutboundHandlerA:UnpooledHeapByteBuf(ridx: 0, widx: 1, cap: 1/1)
根据输出得到以下流程:
虽然InboundHandler与OutboundHandler在同一个双向链表中,但是这两类Handler分工是不同的,通常是同类之间传播事件。