Netty框架的简单实现(客户端和服务端收发消息)


Netty框架的简单实现

一、Netty的原理分析图

 

 

 

 

 二、使用Netty框架的简单实现(实现client和server的消息收发)

   (1)NettyServer

 1 public class NettyServer {  2     public static void main(String[] args) throws Exception{  3         
 4          //创建两个线程池  5          
 6         //创建一个线程组,接收客户端的连接
 7         EventLoopGroup bossGroup = new NioEventLoopGroup();  8         //创建一个线程组,用于处理网络操作
 9         EventLoopGroup workerGroup = new NioEventLoopGroup(); 10         //创建服务器端启动助手(用于配置参数)
11         ServerBootstrap serverBootstrap = new ServerBootstrap(); 12         serverBootstrap.group(bossGroup,workerGroup)//设置两个线程组
13         .channel(NioServerSocketChannel.class)//精华部分,设置通道的底层实现, 14         //通过NioServerSocketChannel 15         //这也是Netty的与NIO搭配的地方(此处作为服务器端通道的实现)
16         .option(ChannelOption.SO_BACKLOG, 12)//设置线程队列中等待连接的个数
17         .childOption(ChannelOption.SO_KEEPALIVE, true) 18         //是否启用心跳保活机制。在双方TCP套接字建立连接后(即都进入ESTABLISHED状态)并 19          //且在两个小时左右 20          //上层没有任何数据传输的情况下,这套机制才会被激活。
21          * */
22         .childHandler(new ChannelInitializer<SocketChannel>() {//(用内部类的方法) 23         //创建一个通道初始化对象
24             public void initChannel(SocketChannel sc){ 25                 sc.pipeline().addLast(new NettyServerHandler());//往pipeline链中添加 26                 //自定义的handler类
27  } 28  }); 29         System.out.println("...Server is Ready..."); 30         //ChannelFuture接口,用于在之后的某个时间点确定结果
31         ChannelFuture sf = serverBootstrap.bind(9999).sync();//绑定端口 非阻塞 异步
32         System.out.println("....Server is Start...."); 33         //关闭通道,关闭线程组
34  sf.channel().closeFuture().sync(); 35  bossGroup.shutdownGracefully(); 36  workerGroup.shutdownGracefully(); 37  } 38 }

  (2)NettyServerHandler

 1 //服务器中的业务处理类
 2 public class NettyServerHandler extends ChannelInboundHandlerAdapter {  3 
 4     //数据读取事件
 5     public void channelRead(ChannelHandlerContext ctx,Object msg){  6         //传来的消息包装成字节缓冲区
 7         ByteBuf byteBuf = (ByteBuf) msg;  8         //Netty提供了字节缓冲区的toString方法,并且可以设置参数为编码格式:CharsetUtil.UTF_8
 9         System.out.println("客户端发来的消息:" + byteBuf.toString(CharsetUtil.UTF_8)); 10  } 11 
12     //数据读取完毕事件
13     public void channelReadComplete(ChannelHandlerContext ctx){ 14          //数据读取完毕,将信息包装成一个Buffer传递给下一个Handler,Unpooled.copiedBuffer会返回一个Buffer 15         //调用的是事件处理器的上下文对象的writeAndFlush方法 16         //意思就是说将 你好 传递给了下一个handler
17         ctx.writeAndFlush(Unpooled.copiedBuffer("你好!", CharsetUtil.UTF_8)); 18  } 19 
20     //异常发生的事件
21     public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause){ 22         //异常发生时关闭上下文对象
23  ctx.close(); 24  } 25 }

  (3)NettyClient

 1 //网络客户端
 2 public class NettyClient {  3     public static void main(String[] args) throws Exception{  4         //创建一个线程组(不像服务端需要有连接等待的线程池)
 5         EventLoopGroup group = new NioEventLoopGroup();  6         //创建客户端的服务启动助手完成相应配置
 7         Bootstrap b = new Bootstrap();  8  b.group(group)  9                 .channel(NioSocketChannel.class) 10                 .handler(new ChannelInitializer<SocketChannel>() {//创建一个通道初始化对象
11  @Override 12                     protected void initChannel(SocketChannel socketChannel) throws Exception { 13                         socketChannel.pipeline().addLast(new NettyClientHandler());//往pipeline中添加自定义的handler
14  } 15  }); 16         System.out.println("...Client is Ready..."); 17         //启动客户端去连接服务器端(通过启动助手)
18         ChannelFuture cf = b.connect("127.0.0.1", 9999).sync(); 19         //关闭连接(异步非阻塞)
20  cf.channel().closeFuture().sync(); 21 
22  } 23 }

  (4)NettyClientHandler

 1 //客户端业务处理类
 2 public class NettyClientHandler extends ChannelInboundHandlerAdapter {  3 
 4     //通道就绪事件(就是在bootstrap启动助手配置中addlast了handler之后就会触发此事件)  5     //但我觉得也可能是当有客户端连接上后才为一次通道就绪
 6     public void channelActive(ChannelHandlerContext ctx){  7         System.out.println("Client :" + ctx);  8         //向服务器端发消息
 9         ctx.writeAndFlush(Unpooled.copiedBuffer("你好啊!", CharsetUtil.UTF_8)); 10  } 11     //数据读取事件
12     public void channelRead(ChannelHandlerContext ctx,Object msg){ 13         //传来的消息包装成字节缓冲区
14         ByteBuf byteBuf = (ByteBuf) msg; 15         //Netty提供了字节缓冲区的toString方法,并且可以设置参数为编码格式:CharsetUtil.UTF_8
16         System.out.println("服务器端发来的消息:" + byteBuf.toString(CharsetUtil.UTF_8)); 17  } 18 
19 }

  通道的消息处理都是通过channelHandlerContext对象的writeAndFlush方法来处理的。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM