netty学习记录
-
NioEventLoopGroup
- 线程数量默认为:处理器数量*2
DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
"io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
-
ChannelInboundHandlerAdapter
1.channelRead,msg正确处理
//方式一 public void channelRead(ChannelHandlerContext ctx, Object msg) { try { // Do something with msg } finally { ReferenceCountUtil.release(msg); } } //方式二 public void channelRead(ChannelHandlerContext ctx, Object msg) { // Netty releases it for you when it is written out to the wire ctx.write(msg); // (1) ctx.flush(); // (2) }
-
DefaultChannelGroup
- 线程安全的channel集合,对channel提供多种操作
- 广播一个消息到多个channels
ChannelGroup recipients = new DefaultChannelGroup(); recipients.add(channelA); recipients.add(channelB); //.. recipients.write(ChannelBuffers.copiedBuffer( "Service will shut down for maintenance in 5 minutes.", CharsetUtil.UTF_8));
- 简单关闭多个channels
ChannelGroup allChannels = new DefaultChannelGroup(); public static void main(String[] args) throws Exception { ServerBootstrap b = new ServerBootstrap(..); //... // Start the server b.getPipeline().addLast("handler", new MyHandler()); Channel serverChannel = b.bind(..); allChannels.add(serverChannel); //... Wait until the shutdown signal reception ... // Close the serverChannel and then all accepted connections. allChannels.close().awaitUninterruptibly(); b.releaseExternalResources(); } public class MyHandler extends SimpleChannelUpstreamHandler { @Override public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) { // Add all open channels to the global group so that they are // closed on shutdown. allChannels.add(e.getChannel()); } }
管理channels
public void channelActive(ChannelHandlerContext ctx) throws Exception { // logger.debug("channelActive"); NettyServer.ALL_CHANNELS.add(ctx.channel()); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { // logger.debug("channelInactive"); NettyServer.ALL_CHANNELS.remove(ctx.channel()); }
-
ChannelHandlerContext记录问题
- 如果要在内存记下ctx,要注意记录的是哪一个
protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); // Add the message codec first, pipeline.addLast("decode", new NetDecodeHandler(serverManager.getConfig().baseProtocol)); pipeline.addLast("encode", new NetEncodeHandler(serverManager.getConfig().baseProtocol)); // and then business logic. pipeline.addLast("serverHandler", new NetServerHandler(serverManager)); Glog.debug("NetServerInitializer:pipeline={}", pipeline); }
假如在NetEncodeHandler中记录ctx,调用ctx.writeAndFlush将直接写入到pipeline中的headercontext,不会经过NetEncodeHandler处理。通常应该记录
NetServerHandler中的ctx,这时候调用ctx.writeAndFlush将会经过NetEncodeHandler处理public class NetDecodeHandler extends ByteToMessageDecoder { private IProtocol baseProtocol; public NetDecodeHandler(IProtocol baseProtocol) { this.baseProtocol = baseProtocol; } @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { if(!in.isReadable() || in.readableBytes() < 4) { return; } while (in.readableBytes() >= 4) { in.markReaderIndex(); int dataLength = in.readInt(); if (in.readableBytes() < dataLength) { in.resetReaderIndex(); return; } byte[] data = new byte[dataLength]; in.readBytes(data); out.add(baseProtocol.decode(data)); } } }
浙公网安备 33010602011771号