netty上手
关于netty的基础NIO,请参见:NIO原理及实例
下面介绍Netty的上手使用;
首先为项目添加jar依赖:
<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.8.Final</version> </dependency>
1、开始写代码,一般是先写输入输出的逻辑(handler)
handler一般继承于SimpleChannelInboundHandler 或者 ChannelOutboundHandlerAdapter,区别在于simple。。不需要手动释放消息
输入handler 继承于SimpleChannelInboundHandler
package com.pt.netty.client; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; /** * @author panteng * @description 继承自simple会自动释放数据,否则需要手动释放 * @date 17-3-19. */ @ChannelHandler.Sharable public class InputHandler1 extends SimpleChannelInboundHandler<ByteBuf> { /** * 读数据 * * @param channelHandlerContext * @param byteBuf * @throws Exception */ @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception { System.out.println("InputHandler1:channelRead0"); } /** * 读数据,首先调此函数,父类默认调用channelRead0 * * @param ctx * @param msg * @throws Exception */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("InputHandler1:channelRead"); if (msg instanceof ByteBuf) { System.out.println(new String(ByteBufUtil.getBytes((ByteBuf) msg))); } ctx.writeAndFlush(Unpooled.copiedBuffer("OK".getBytes())); ctx.fireChannelRead(msg); // super.channelRead(ctx, msg); } /** * 连接成功 * * @param ctx * @throws Exception */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("InputHandler1:channelActive 连接成功"); // super.channelActive(ctx); } /** * 异常处理 * * @param ctx * @param cause * @throws Exception */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); super.exceptionCaught(ctx, cause); } }
package com.pt.netty.client; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; /** * @author panteng * @description 继承自simple会自动释放数据,否则需要手动释放 * @date 17-3-19. */ @ChannelHandler.Sharable public class InputHandler2 extends SimpleChannelInboundHandler<ByteBuf> { /** * 读数据 * * @param channelHandlerContext * @param byteBuf * @throws Exception */ @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception { System.out.println("InputHandler2:channelRead0"); } /** * 读数据,首先调此函数,父类默认调用channelRead0 * * @param ctx * @param msg * @throws Exception */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("InputHandler2:channelRead"); // super.channelRead(ctx, msg); } /** * 连接成功 * * @param ctx * @throws Exception */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("InputHandler2:channelActive 连接成功"); // super.channelActive(ctx); } /** * 异常处理 * * @param ctx * @param cause * @throws Exception */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); super.exceptionCaught(ctx, cause); } }
输出handler
package com.pt.netty.client; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelOutboundHandlerAdapter; import io.netty.channel.ChannelPromise; /** * 继承ChannelOutboundHandlerAdapter方法时,必须执行super.方法,否则阻塞无法执行 * * @author panteng * @description * @date 17-3-19. */ public class OutputHandler extends ChannelOutboundHandlerAdapter { @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { // super.write(ctx, msg, promise); System.out.println("OutputHandler:write"); ctx.write(msg); } }
2、main函数
package com.pt.netty.client; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; /** * @author panteng * @description * @date 17-3-19. */ public class ClientOfNetty { public static void main(String[] arges) { // 可以指定线程数目(不指定采用默认值 CPU的2倍) EventLoopGroup group = new NioEventLoopGroup(1); try { Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group).channel(NioSocketChannel.class).remoteAddress("10.232.36.21", 4700) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new OutputHandler()); socketChannel.pipeline().addLast(new InputHandler1()); socketChannel.pipeline().addLast(new InputHandler2()); } }); ChannelFuture f = bootstrap.connect().sync();// 阻塞 Thread.sleep(5000); f.channel().close().sync(); } catch (Exception e) { e.printStackTrace(); } finally { group.shutdownGracefully(); } System.out.println("退出主函数。。。 。。。"); } }