0%

ChannelHandler

ChannelHandler

Netty使用ChannelHandler来进行数据处理,且可以连接每个ChannelHandler。ChannelPipeline和ChannelHandler机制类似于Servlet和Filter过滤器链,将Channel的数据管道抽象为ChannelPipeline,消息在ChannelPipeline中流动和传递,交给ChannelHandler进行处理。

ChannelPipeline

ChannelPipeline持有ChannelHandler实例的链表,提供了一种高级的截取过滤器模式,可以通过新增和删除来实现不同的业务逻辑定制,而不需要对已有的ChannelHandler进行修改。让用户可以在ChannelPipeline中完全控制一个事件及如何处理ChannelHandler与ChannelPipeline的交互。

1
2
3
4
5
6
7
8
9
10
final AbstractChannelHandlerContext head;
final AbstractChannelHandlerContext tail;

private void addLast0(AbstractChannelHandlerContext newCtx) {
AbstractChannelHandlerContext prev = tail.prev;
newCtx.prev = prev;
newCtx.next = tail;
prev.next = newCtx;
tail.prev = newCtx;
}

在进行read操作时,调用顺序为head->tail;在进行write操作时,调用顺序为tail->head

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
*                                                 I/O Request
* via {@link Channel} or
* {@link ChannelHandlerContext}
* |
* +---------------------------------------------------+---------------+
* | ChannelPipeline | |
* | \|/ |
* | +---------------------+ +-----------+----------+ |
* | | Inbound Handler N | | Outbound Handler 1 | |
* | +----------+----------+ +-----------+----------+ |
* | /|\ | |
* | | \|/ |
* | +----------+----------+ +-----------+----------+ |
* | | Inbound Handler N-1 | | Outbound Handler 2 | |
* | +----------+----------+ +-----------+----------+ |
* | /|\ . |
* | . . |
* | ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()|
* | [ method call] [method call] |
* | . . |
* | . \|/ |
* | +----------+----------+ +-----------+----------+ |
* | | Inbound Handler 2 | | Outbound Handler M-1 | |
* | +----------+----------+ +-----------+----------+ |
* | /|\ | |
* | | \|/ |
* | +----------+----------+ +-----------+----------+ |
* | | Inbound Handler 1 | | Outbound Handler M | |
* | +----------+----------+ +-----------+----------+ |
* | /|\ | |
* +---------------+-----------------------------------+---------------+
* | \|/
* +---------------+-----------------------------------+---------------+
* | | | |
* | [ Socket.read() ] [ Socket.write() ] |
* | |
* | Netty Internal I/O Threads (Transport Implementation) |
* +-------------------------------------------------------------------+

Netty中的事件分为Inbound事件和Outbound事件。Inbound事件通常由IO线程触发,如TCP链路建立事件、链路关闭事件、读事件等,触发Inbound的方法有ChannelHandlerContext中的(继承自ChannelInboundInvoker接口的方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Channel注册事件
ChannelHandlerContext fireChannelRegistered();

// Channel卸载事件
ChannelHandlerContext fireChannelUnregistered();

// TCP建立成功,Channel激活事件
ChannelHandlerContext fireChannelActive();

// TCP连接关闭
ChannelHandlerContext fireChannelInactive();

// 异常通知事件
ChannelHandlerContext fireExceptionCaught(Throwable cause);

// 用户自定义事件
ChannelHandlerContext fireUserEventTriggered(Object event);

// 读事件
ChannelHandlerContext fireChannelRead(Object msg);

// 读操作完成通知事件
ChannelHandlerContext fireChannelReadComplete();

// Channel的可写状态变化通知事件
ChannelHandlerContext fireChannelWritabilityChanged();

Outbound事件通常是由用户主动发起的网络IO操作,如用户发起的连接操作、绑定操作、消息发送等,触发Outbound事件的方法有ChannelHandlerContext中的(继承自ChannelInboundInvoker接口的方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 绑定本地地址事件
ChannelFuture bind(SocketAddress localAddress);

// 连接服务端事件
ChannelFuture connect(SocketAddress remoteAddress);

// 断开连接事件
ChannelFuture disconnect();

// 关闭channel事件
ChannelFuture close();

// 读事件
ChannelHandlerContext read();

// 发送事件
ChannelFuture write(Object msg);

// 刷新事件
ChannelHandlerContext flush();

ChannelHandlerContext

每个ChannelHandler被添加到ChannelPipeline后,都会创建一个ChannelHandlerContext并与之创建的ChannelHandler关联绑定

欢迎关注我的其它发布渠道