Netty之ChannelHandler事件

ChannelHandler事件

Netty是一款基于事件驱动的异步I/O框架.因此有很多事件.有时候不清楚事件是什么时候触发的,这里总结一下.

inbound事件

入站事件,在Netty中入站事件是相对于被动发生的一些事件.比如说可读,写事件改变.是从管道的头部向尾部流动.

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public class TestMethodHandler extends ChannelInboundHandlerAdapter {


// 在将此handler添加到管道中的时候会触发此事件.
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
System.out.println("HandlerAdd");
}

// 在将此handler从管道中移除的时候会触发此事件
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
System.out.println("HandlerRemove");
}
// 在此handler对应的pipeline对应的Channel注册到多路复用器上时触发.在handlerAdd之后
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("registered");
}
// 取消注册时候触发
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("unregistered");
}

// 连接建立之后触发,在handlerAdd和channelRegister之后
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelActive");
}
// 连接关闭之后触发,在handlerRemove之前
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelInActive");
}

// 当Channel可读之后,会触发.
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("channelRead");
ctx.write(Unpooled.copiedBuffer("hello".getBytes()));

ctx.fireUserEventTriggered("bac");
}
// 一次读操作完成会调用.并不一定是读取一个数据包.这里一次可能读取不了全部的消息,所以分步读取.如果很大的数据包,会分很多次读取.
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
System.out.println("readComplete");
}
// 触发的用户事件,可以自己定义.需要自己手动调用ctx.fireUserEventTriggered()方法触发
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
System.out.println("eventTriggered");
}

// 在写状态改变的时候触发.这个情况一般发生在发送数据太多,对方的接收缓冲区满了,因此不可写,之后等待对方可写之后会触发此事件.
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
System.out.println("writeChanged");
}
// 发生异常时候触发
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println("exception");
}
}

outbound事件

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
出站事件,相对来说是主动发生的事件,需要用户手动去调用的事件.数据流动为从尾部到头部.
public class TestOutboundMethodHandler extends ChannelOutboundHandlerAdapter {

// 执行绑定端口的时候调用此函数
@Override
public void bind(ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) throws Exception {
System.out.println("bind");
super.bind(ctx, localAddress, promise);
}
// 发起连接的时候调用
@Override
public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) throws Exception {
System.out.println("connect");
super.connect(ctx, remoteAddress, localAddress, promise);
}
// 断开连接时候调用
@Override
public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
System.out.println("disconnect");
super.disconnect(ctx, promise);
}
// 关闭Channel时候调用,或者手动触发ctx.close()
@Override
public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
System.out.println("close");
super.close(ctx, promise);
}
//调用ctx.deregister()方法才可以
@Override
public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
System.out.println("deregister");
super.deregister(ctx, promise);
}
// 这里的读事件并不同于入站的读事件,而是注册读事件,是一个主动的动作.
// 如果设置了自动读参数,则会在每次读操作完成之后调用此函数.
// 为什么会有这个方法存在呢,首先是因为有些服务器只接受消息,没必要注册读事件,因此可以设置为不注册读
// 其次是因为Netty在每次读事件发生的时候总是先取消掉selectionKey的可读事件,因此在读玩之后需要再次加上去
@Override
public void read(ChannelHandlerContext ctx) throws Exception {
System.out.println("read");
super.read(ctx);
}
// 写数据会触发
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
System.out.println("write");
super.write(ctx, msg, promise);
}
// 刷新数据才会触发
@Override
public void flush(ChannelHandlerContext ctx) throws Exception {
System.out.println("flush");
super.flush(ctx);
}
}