- 在
io.netty.channel.ChannelPipeline
这个Java类中, 有这样的注释
1.事件
- 上文中我们了解到Netty是一个事件驱动的网络模型
- 所以在Netty编程中, 一切皆事件, 我们解决问题的最小单元就是事件
- Netty把很多操作, 都切分开来抽象成了一堆事件
先暂时不要细究事件是个啥, 你先把它当做成一个在handler之间流转的Java对象, 后面我们再详细讨论
2.pipeline
现在你知道了Netty里面把万物都抽象成了事件, 好了, 我们现在需要了解一下事件是怎么流动的
这里Netty设计了一个pipeline的概念 (实际上是一种责任链的设计模式)
2.1 出站与入站
pipeline有两条平行线, 这两条线就是事件流转的路线
- 入站线路: 一条起点是socket, 接收网络数据之后, 数据包会变换成各种事件, 顺着入站线路流转
出站线路: 另一条的终点是socket, 我们的程序可以把事件丢入出站线路
2.2 ChannelHandler
ChannelHandler在pipeline上处理各种事件的对象
- 而这些handler又分为
- 专门处理入站事件的 ChannelInboundHandler
专门处理出站事件的 ChannelOutboundHandler
2.2.1 ChannelInboundHandler
io.netty.channel.ChannelInboundHandler
下面三个方法比较重要
public interface ChannelInboundHandler extends ChannelHandler {
/**
* 建立TCP连接的时候会被调用
*/
void channelActive(ChannelHandlerContext ctx) throws Exception;
/**
* 当读取到新的数据的时候会被调用
* 这里需要解决半包粘包问题
*/
void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception;
/**
* 当前读操作读取的最后一条消息被channelRead使用
* 然后会调用此方法
*/
void channelReadComplete(ChannelHandlerContext ctx) throws Exception;
}
2.2.2 ChannelOutboundHandler
io.netty.channel.ChannelOutboundHandler
public interface ChannelOutboundHandler extends ChannelHandler {
/**
* ChannelHandlerContext
* ctx.writeAndFlush(msg);
* ctx.write(msg);
*/
void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception;
/**
* ChannelHandlerContext
* ctx.writeAndFlush(msg);
* ctx.flush(msg);
*/
void flush(ChannelHandlerContext ctx) throws Exception;
}
2.2.3 ChannelDuplexHandler
结合了InboundHandler和OutboundHandler的handler
public class ChannelDuplexHandler extends ChannelInboundHandlerAdapter
implements ChannelOutboundHandler {
}
2.2.3 ChannelHandlerContext
好了有pipeline, 有handler, 那么如何控制handler流转呢?
一个handler处理完之后, 是该继续入站, 还是出站呢?io.netty.channel.ChannelHandlerContext
这个接口是操作事件在pipeline中流转的方向
ctx.fireChannelRead()
: 可以将事件对象以入站的方向,向后流转, 转给其他ChannelInboundHandler处理ctx.write()
: 可以将事件传送到出站方向的下一个handler的write()方法中ctx.writeAndFlush()
: 可以将事件传送到出站方向的下一个handler的write()方法中, 再调用flush()ctx.channel().write()
: 将事件送到整个pipeline的尾部, 再出站, handler逐个处理