• 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方法来处理的。

  • 相关阅读:
    Mysql使用存储过程快速添加百万数据
    ArcMap连接远程数据库报错“ Connection was attempted with an older version of SQL Server client communications software that is not supported.”
    uart write example
    Solution to errors like /lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found
    读.txt数据并合并~读npy数据并合并
    JVM类加载路径查看
    磨人的R语言安装问题(以安装monocle为例)
    js 删除数组几种方法
    vue 脚手架运行报错常见问题--'webpack-dev-server' 不是内部或外部命令,也不是可运行的程序 或批处理文件
    vue 脚手架运行报错常见问题--vue-cli Failed to download repo vuejs-templates/webpack
  • 原文地址:https://www.cnblogs.com/dashenaichicha/p/12095191.html
Copyright © 2020-2023  润新知