ChannelInitializer: 每个channel都new ChannelHandle
State management
1.业务状态管理-是否登录
A ChannelHandler
often needs to store some stateful information. The simplest and recommended approach is to use member variables:
public interface Message { // your methods here } public class DataServerHandler extends SimpleChannelInboundHandler<Message> { private boolean loggedIn; @Override public void channelRead0(ChannelHandlerContext ctx, Message message) { Channel ch = e.getChannel(); if (message instanceof LoginMessage) { authenticate((LoginMessage) message); loggedIn = true; } else (message instanceof GetDataMessage) { if (loggedIn) { ch.write(fetchSecret((GetDataMessage) message)); } else { fail(); } } } ... }
Because the handler instance has a state variable which is dedicated to one connection, you have to create a new handler instance for each new channel to avoid a race condition where a unauthenticated client can get the confidential information:
// Create a new handler instance per channel. // See ChannelInitializer.initChannel(Channel). public class DataServerInitializer extends ChannelInitializer<Channel> { @Override public void initChannel(Channel channel) { channel.pipeline().addLast("handler", new DataServerHandler()); } }
2。channel 自身状态管理
public class HeartbeatHandlerInitializer extends ChannelInitializer<Channel> { private static final int READ_IDEL_TIME_OUT = 10; // 读超时 private static final int WRITE_IDEL_TIME_OUT = 10;// 写超时 private static final int ALL_IDEL_TIME_OUT = 0; // 所有超时 @Override protected void initChannel(Channel ch) throws Exception { System.out.println( "channelId" + ch.id()); //一直执行,一直打印 while (ch.eventLoop().iterator().hasNext()){ System.out.println(ch.eventLoop().iterator().next().inEventLoop()); } ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new IdleStateHandler(READ_IDEL_TIME_OUT, WRITE_IDEL_TIME_OUT, ALL_IDEL_TIME_OUT, TimeUnit.SECONDS)); // 1 pipeline.addLast(new HeartbeatServerHandler()); } }