本例介绍Netty基本服务端和客户端
一、服务端Netty的工作架构
二、Netty服务端
代码如下:
1、NettyServer.java 服务端主类
1 public class NettyServer { 2 3 public static void main(String[] args) throws InterruptedException { 4 5 // 创建EventLoopGroup 6 NioEventLoopGroup bossGroup = new NioEventLoopGroup(1); 7 NioEventLoopGroup workerGroup = new NioEventLoopGroup(); 8 9 try { 10 // 创建ServerBootstrap 11 ServerBootstrap bootstrap = new ServerBootstrap(); 12 13 // 配置bootstrap 14 bootstrap.group(bossGroup, workerGroup) 15 // 指定使用的 NIO传输Channel 16 .channel(NioServerSocketChannel.class) 17 // 指定端口,设置套接字地址 18 .localAddress(new InetSocketAddress(9000)) 19 // 添加处理器 20 .childHandler(new ChannelInitializer<SocketChannel>() { 21 @Override 22 protected void initChannel(SocketChannel ch) throws Exception { 23 // 初始化channel时,添加处理器 24 ch.pipeline().addLast(new NettyServerHandler()); 25 } 26 }); 27 28 // 绑定端口 29 // sync():调用sync()方法阻塞等待知道绑定完成 30 ChannelFuture channelFuture = bootstrap.bind().sync(); 31 // 获取Channel的CloseFuture,并阻塞知道它完成 32 channelFuture.channel().closeFuture().sync(); 33 } finally { 34 // 关闭释放资源 35 bossGroup.shutdownGracefully().sync(); 36 workerGroup.shutdownGracefully().sync(); 37 } 38 39 } 40 }
2、NettyServerHandler.java 服务端处理类
1 public class NettyServerHandler extends ChannelInboundHandlerAdapter { 2 3 // 对于每个传入的消息都要调用 4 @Override 5 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 6 // 记录已接收的消息 7 ByteBuf byteBuf = (ByteBuf) msg; 8 System.out.println("Server received: " + byteBuf.toString(CharsetUtil.UTF_8)); 9 } 10 11 // 通知 ChannelInboundHandlerAdapter 最后一次 channelRead()的调用 12 // 是当前批量读取中的最后一条消息 13 @Override 14 public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { 15 // 将未决消息冲刷到远程节点,并且关闭该Channel; 16 ctx.writeAndFlush(Unpooled.EMPTY_BUFFER) 17 .addListener(ChannelFutureListener.CLOSE); 18 System.out.println("读取完成"); 19 } 20 21 // 在读取操作期间,有异常抛出时调用 22 @Override 23 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 24 // 打印异常 25 cause.printStackTrace(); 26 // 关闭Channel 27 ctx.channel(); 28 } 29 }
三、Netty客户端
代码如下:
1、NettyClient.java 客户端主类
1 public class NettyClient { 2 public static void main(String[] args) throws InterruptedException { 3 // 事件循环组 4 NioEventLoopGroup group = new NioEventLoopGroup(); 5 try { 6 // 启动对象 7 Bootstrap bootstrap = new Bootstrap(); 8 // 配置 9 bootstrap.group(group) 10 .channel(NioSocketChannel.class) 11 .remoteAddress(new InetSocketAddress("127.0.0.1",9000)) 12 .handler(new ChannelInitializer<SocketChannel>() { 13 @Override 14 protected void initChannel(SocketChannel ch) throws Exception { 15 ch.pipeline().addLast(new NettyClientHandler()); 16 } 17 }); 18 19 // 连接远程地址,阻塞至连接完成 20 ChannelFuture channelFuture = bootstrap.connect().sync(); 21 // 阻塞直到channel关闭 22 channelFuture.channel().closeFuture().sync(); 23 } finally { 24 // 关闭释放资源 25 group.shutdownGracefully().sync(); 26 } 27 } 28 }
2、NettyClientHandler.java 客户端处理类
1 public class NettyClientHandler extends SimpleChannelInboundHandler<ByteBuf> { 2 3 // 当从服务器接收到一条消息时被调用 4 @Override 5 protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { 6 // 记录已接收的消息 7 System.out.println("Client received: " + msg.toString(CharsetUtil.UTF_8)); 8 } 9 10 // 在到服务器的连接已建立之后将被调用 11 @Override 12 public void channelActive(ChannelHandlerContext ctx) throws Exception { 13 // 当被通知Channel是活跃的时侯,发送一条消息 14 ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8)); 15 } 16 17 // 在处理过程中引发异常时调用 18 @Override 19 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 20 // 打印异常 21 cause.printStackTrace(); 22 // 关闭Channel 23 ctx.channel(); 24 } 25 }